¶

Машинное обучение. ВМК МГУ¶

Практическое задание 8: Градиентный бустинг деревьев¶

Важно! О формате сдачи¶

  • Практически все выделенные задания из ноутбука оцениваются по системе кросс-рецензирования. Задания, в которых надо реализовать свой код и послать в систему, выделены здесь и в PDF отдельно.
  • В этом задании также есть задания по типу ML-решения.
  • При решении ноутбука используйте данный шаблон. Не нужно удалять текстовые ячейки с разметкой частей ноутбука и формулировками заданий. Добавлять свои ячейки, при необходимости, конечно, можно.
  • Везде, где в формулировке задания есть какой-либо вопрос (или просьба вывода), необходимо прописать ответ в ячейку (код или Markdown).
  • Наличие кода решения обязательно. Письменные ответы на вопросы без сопутствующего кода оцениваются в 0 баллов.
  • Если в ячейке написана фраза "Вывод"/"Ответ на вопрос" и.т.д., то ожидается ответ в виде текста (можете добавить ячейки с кодом, если считаете это необходимым, но это необязательно). Если в ячейке написано "Your code here" и пр. , то ожидается ответ в виде кода (можете добавить ячейки с кодом, если считаете это необходимым, но это необязательно). Если есть и ячейка с фразой "Вывод", и ячейка с фразой "Your code here", то в ответе ожидается и код, и текст

В этом задании вы..:

  • Познакомитесь с несколькими новыми библиотеками машинного обучения
  • Сравните между собой разные реализации градиентных бустингов
  • Примените все полученные знания для получения лучшего скора на датасете фильмов

*Примерное время выполнения (execution time/время выполнения, если нажать run all) всех ячеек ноутбука (без ML-решения): 60 минут*</h3>


cНемного магии, которую не надо менять, но надо выполнить перед каждым запуском!

Подготовка рабочей среды¶

Сначала установим нужные нам версии библиотек. Мы гарантируем, что в данных версиях задание будет корректно отрабатывать.

После установки нужных версий, возможно, нужно перезагрузить среду (runtime), но скорее всего вам это не понадобится

На скачивание файла и установку понадобится не более 5 минут.

Важно! Устанавливать нужные версии нужно каждый раз, когда создается новый рантайм. Например, если вы 2 часа подряд делаете это задание, то подготовить библиотеки достаточно 1 раз. Но если вы, например, начали в понедельник, затем закрыли/выключили ноутбук, то при продолжении в среду, вам нужно будет запустить рантайм заново и следовательно заново установить библиотеки.

Важно! Если вы предпочитаете делать практические задания на своем личном ноутбуке, то проверьте, что вы установили рабочее окружение в соответствии с гайдом

**Важно!** В файлике requirementssmall.txt поменялась версия gdown (в предыдущей версии, к сожалению, стали появляться ошибки при скачивании через эту утилиту)_! Если вы работаете в Google Colab, то ничего дополнительно делать не нужно, если вы работаете локально, то рекомендуем обновить версию gdown в виртуальном окружении на >=4.7.3. Более подробные инструкции вы найдете в треде по этому заданию в чате курса.

In [ ]:
!pip install --upgrade gdown
Requirement already satisfied: gdown in /usr/local/lib/python3.10/dist-packages (5.1.0)
Requirement already satisfied: beautifulsoup4 in /usr/local/lib/python3.10/dist-packages (from gdown) (4.12.3)
Requirement already satisfied: filelock in /usr/local/lib/python3.10/dist-packages (from gdown) (3.13.1)
Requirement already satisfied: requests[socks] in /usr/local/lib/python3.10/dist-packages (from gdown) (2.31.0)
Requirement already satisfied: tqdm in /usr/local/lib/python3.10/dist-packages (from gdown) (4.66.1)
Requirement already satisfied: soupsieve>1.2 in /usr/local/lib/python3.10/dist-packages (from beautifulsoup4->gdown) (2.5)
Requirement already satisfied: charset-normalizer<4,>=2 in /usr/local/lib/python3.10/dist-packages (from requests[socks]->gdown) (3.3.2)
Requirement already satisfied: idna<4,>=2.5 in /usr/local/lib/python3.10/dist-packages (from requests[socks]->gdown) (3.6)
Requirement already satisfied: urllib3<3,>=1.21.1 in /usr/local/lib/python3.10/dist-packages (from requests[socks]->gdown) (2.0.7)
Requirement already satisfied: certifi>=2017.4.17 in /usr/local/lib/python3.10/dist-packages (from requests[socks]->gdown) (2024.2.2)
Requirement already satisfied: PySocks!=1.5.7,>=1.5.6 in /usr/local/lib/python3.10/dist-packages (from requests[socks]->gdown) (1.7.1)
In [ ]:
!gdown 1pIw8GdGKY6fZ_XNPc6snimdV6lbXJ199
!pip install -r /content/requirements_small.txt
Downloading...
From: https://drive.google.com/uc?id=1pIw8GdGKY6fZ_XNPc6snimdV6lbXJ199
To: /content/requirements_small.txt
100% 374/374 [00:00<00:00, 1.46MB/s]
Requirement already satisfied: catboost==1.2.1 in /usr/local/lib/python3.10/dist-packages (from -r /content/requirements_small.txt (line 1)) (1.2.1)
Requirement already satisfied: gdown==5.1.0 in /usr/local/lib/python3.10/dist-packages (from -r /content/requirements_small.txt (line 2)) (5.1.0)
Requirement already satisfied: h5py==3.9.0 in /usr/local/lib/python3.10/dist-packages (from -r /content/requirements_small.txt (line 3)) (3.9.0)
Requirement already satisfied: hyperopt==0.2.7 in /usr/local/lib/python3.10/dist-packages (from -r /content/requirements_small.txt (line 4)) (0.2.7)
Requirement already satisfied: ipympl==0.9.3 in /usr/local/lib/python3.10/dist-packages (from -r /content/requirements_small.txt (line 5)) (0.9.3)
Requirement already satisfied: ipywidgets==7.7.1 in /usr/local/lib/python3.10/dist-packages (from -r /content/requirements_small.txt (line 6)) (7.7.1)
Requirement already satisfied: lightgbm==4.0.0 in /usr/local/lib/python3.10/dist-packages (from -r /content/requirements_small.txt (line 7)) (4.0.0)
Requirement already satisfied: matplotlib==3.7.1 in /usr/local/lib/python3.10/dist-packages (from -r /content/requirements_small.txt (line 8)) (3.7.1)
Requirement already satisfied: matplotlib-inline==0.1.6 in /usr/local/lib/python3.10/dist-packages (from -r /content/requirements_small.txt (line 9)) (0.1.6)
Requirement already satisfied: numpy==1.23.5 in /usr/local/lib/python3.10/dist-packages (from -r /content/requirements_small.txt (line 10)) (1.23.5)
Requirement already satisfied: pandas==1.5.3 in /usr/local/lib/python3.10/dist-packages (from -r /content/requirements_small.txt (line 11)) (1.5.3)
Requirement already satisfied: pep8==1.7.1 in /usr/local/lib/python3.10/dist-packages (from -r /content/requirements_small.txt (line 12)) (1.7.1)
Requirement already satisfied: plotly==5.15.0 in /usr/local/lib/python3.10/dist-packages (from -r /content/requirements_small.txt (line 13)) (5.15.0)
Requirement already satisfied: pycodestyle==2.11.0 in /usr/local/lib/python3.10/dist-packages (from -r /content/requirements_small.txt (line 14)) (2.11.0)
Requirement already satisfied: pytest==7.4.1 in /usr/local/lib/python3.10/dist-packages (from -r /content/requirements_small.txt (line 15)) (7.4.1)
Requirement already satisfied: scikit-image==0.19.3 in /usr/local/lib/python3.10/dist-packages (from -r /content/requirements_small.txt (line 16)) (0.19.3)
Requirement already satisfied: scikit-learn==1.2.2 in /usr/local/lib/python3.10/dist-packages (from -r /content/requirements_small.txt (line 17)) (1.2.2)
Requirement already satisfied: scipy==1.11.2 in /usr/local/lib/python3.10/dist-packages (from -r /content/requirements_small.txt (line 18)) (1.11.2)
Requirement already satisfied: seaborn==0.12.2 in /usr/local/lib/python3.10/dist-packages (from -r /content/requirements_small.txt (line 19)) (0.12.2)
Requirement already satisfied: tqdm==4.66.1 in /usr/local/lib/python3.10/dist-packages (from -r /content/requirements_small.txt (line 20)) (4.66.1)
Requirement already satisfied: umap-learn==0.5.3 in /usr/local/lib/python3.10/dist-packages (from -r /content/requirements_small.txt (line 21)) (0.5.3)
Requirement already satisfied: xgboost==1.7.6 in /usr/local/lib/python3.10/dist-packages (from -r /content/requirements_small.txt (line 22)) (1.7.6)
Requirement already satisfied: graphviz in /usr/local/lib/python3.10/dist-packages (from catboost==1.2.1->-r /content/requirements_small.txt (line 1)) (0.20.1)
Requirement already satisfied: six in /usr/local/lib/python3.10/dist-packages (from catboost==1.2.1->-r /content/requirements_small.txt (line 1)) (1.16.0)
Requirement already satisfied: beautifulsoup4 in /usr/local/lib/python3.10/dist-packages (from gdown==5.1.0->-r /content/requirements_small.txt (line 2)) (4.12.3)
Requirement already satisfied: filelock in /usr/local/lib/python3.10/dist-packages (from gdown==5.1.0->-r /content/requirements_small.txt (line 2)) (3.13.1)
Requirement already satisfied: requests[socks] in /usr/local/lib/python3.10/dist-packages (from gdown==5.1.0->-r /content/requirements_small.txt (line 2)) (2.31.0)
Requirement already satisfied: networkx>=2.2 in /usr/local/lib/python3.10/dist-packages (from hyperopt==0.2.7->-r /content/requirements_small.txt (line 4)) (3.2.1)
Requirement already satisfied: future in /usr/local/lib/python3.10/dist-packages (from hyperopt==0.2.7->-r /content/requirements_small.txt (line 4)) (0.18.3)
Requirement already satisfied: cloudpickle in /usr/local/lib/python3.10/dist-packages (from hyperopt==0.2.7->-r /content/requirements_small.txt (line 4)) (2.2.1)
Requirement already satisfied: py4j in /usr/local/lib/python3.10/dist-packages (from hyperopt==0.2.7->-r /content/requirements_small.txt (line 4)) (0.10.9.7)
Requirement already satisfied: ipython<9 in /usr/local/lib/python3.10/dist-packages (from ipympl==0.9.3->-r /content/requirements_small.txt (line 5)) (7.34.0)
Requirement already satisfied: ipython-genutils in /usr/local/lib/python3.10/dist-packages (from ipympl==0.9.3->-r /content/requirements_small.txt (line 5)) (0.2.0)
Requirement already satisfied: pillow in /usr/local/lib/python3.10/dist-packages (from ipympl==0.9.3->-r /content/requirements_small.txt (line 5)) (9.4.0)
Requirement already satisfied: traitlets<6 in /usr/local/lib/python3.10/dist-packages (from ipympl==0.9.3->-r /content/requirements_small.txt (line 5)) (5.7.1)
Requirement already satisfied: ipykernel>=4.5.1 in /usr/local/lib/python3.10/dist-packages (from ipywidgets==7.7.1->-r /content/requirements_small.txt (line 6)) (5.5.6)
Requirement already satisfied: widgetsnbextension~=3.6.0 in /usr/local/lib/python3.10/dist-packages (from ipywidgets==7.7.1->-r /content/requirements_small.txt (line 6)) (3.6.6)
Requirement already satisfied: jupyterlab-widgets>=1.0.0 in /usr/local/lib/python3.10/dist-packages (from ipywidgets==7.7.1->-r /content/requirements_small.txt (line 6)) (3.0.10)
Requirement already satisfied: contourpy>=1.0.1 in /usr/local/lib/python3.10/dist-packages (from matplotlib==3.7.1->-r /content/requirements_small.txt (line 8)) (1.2.0)
Requirement already satisfied: cycler>=0.10 in /usr/local/lib/python3.10/dist-packages (from matplotlib==3.7.1->-r /content/requirements_small.txt (line 8)) (0.12.1)
Requirement already satisfied: fonttools>=4.22.0 in /usr/local/lib/python3.10/dist-packages (from matplotlib==3.7.1->-r /content/requirements_small.txt (line 8)) (4.49.0)
Requirement already satisfied: kiwisolver>=1.0.1 in /usr/local/lib/python3.10/dist-packages (from matplotlib==3.7.1->-r /content/requirements_small.txt (line 8)) (1.4.5)
Requirement already satisfied: packaging>=20.0 in /usr/local/lib/python3.10/dist-packages (from matplotlib==3.7.1->-r /content/requirements_small.txt (line 8)) (23.2)
Requirement already satisfied: pyparsing>=2.3.1 in /usr/local/lib/python3.10/dist-packages (from matplotlib==3.7.1->-r /content/requirements_small.txt (line 8)) (3.1.1)
Requirement already satisfied: python-dateutil>=2.7 in /usr/local/lib/python3.10/dist-packages (from matplotlib==3.7.1->-r /content/requirements_small.txt (line 8)) (2.8.2)
Requirement already satisfied: pytz>=2020.1 in /usr/local/lib/python3.10/dist-packages (from pandas==1.5.3->-r /content/requirements_small.txt (line 11)) (2023.4)
Requirement already satisfied: tenacity>=6.2.0 in /usr/local/lib/python3.10/dist-packages (from plotly==5.15.0->-r /content/requirements_small.txt (line 13)) (8.2.3)
Requirement already satisfied: iniconfig in /usr/local/lib/python3.10/dist-packages (from pytest==7.4.1->-r /content/requirements_small.txt (line 15)) (2.0.0)
Requirement already satisfied: pluggy<2.0,>=0.12 in /usr/local/lib/python3.10/dist-packages (from pytest==7.4.1->-r /content/requirements_small.txt (line 15)) (1.4.0)
Requirement already satisfied: exceptiongroup>=1.0.0rc8 in /usr/local/lib/python3.10/dist-packages (from pytest==7.4.1->-r /content/requirements_small.txt (line 15)) (1.2.0)
Requirement already satisfied: tomli>=1.0.0 in /usr/local/lib/python3.10/dist-packages (from pytest==7.4.1->-r /content/requirements_small.txt (line 15)) (2.0.1)
Requirement already satisfied: imageio>=2.4.1 in /usr/local/lib/python3.10/dist-packages (from scikit-image==0.19.3->-r /content/requirements_small.txt (line 16)) (2.31.6)
Requirement already satisfied: tifffile>=2019.7.26 in /usr/local/lib/python3.10/dist-packages (from scikit-image==0.19.3->-r /content/requirements_small.txt (line 16)) (2024.2.12)
Requirement already satisfied: PyWavelets>=1.1.1 in /usr/local/lib/python3.10/dist-packages (from scikit-image==0.19.3->-r /content/requirements_small.txt (line 16)) (1.5.0)
Requirement already satisfied: joblib>=1.1.1 in /usr/local/lib/python3.10/dist-packages (from scikit-learn==1.2.2->-r /content/requirements_small.txt (line 17)) (1.3.2)
Requirement already satisfied: threadpoolctl>=2.0.0 in /usr/local/lib/python3.10/dist-packages (from scikit-learn==1.2.2->-r /content/requirements_small.txt (line 17)) (3.3.0)
Requirement already satisfied: numba>=0.49 in /usr/local/lib/python3.10/dist-packages (from umap-learn==0.5.3->-r /content/requirements_small.txt (line 21)) (0.58.1)
Requirement already satisfied: pynndescent>=0.5 in /usr/local/lib/python3.10/dist-packages (from umap-learn==0.5.3->-r /content/requirements_small.txt (line 21)) (0.5.11)
Requirement already satisfied: jupyter-client in /usr/local/lib/python3.10/dist-packages (from ipykernel>=4.5.1->ipywidgets==7.7.1->-r /content/requirements_small.txt (line 6)) (6.1.12)
Requirement already satisfied: tornado>=4.2 in /usr/local/lib/python3.10/dist-packages (from ipykernel>=4.5.1->ipywidgets==7.7.1->-r /content/requirements_small.txt (line 6)) (6.3.3)
Requirement already satisfied: setuptools>=18.5 in /usr/local/lib/python3.10/dist-packages (from ipython<9->ipympl==0.9.3->-r /content/requirements_small.txt (line 5)) (67.7.2)
Requirement already satisfied: jedi>=0.16 in /usr/local/lib/python3.10/dist-packages (from ipython<9->ipympl==0.9.3->-r /content/requirements_small.txt (line 5)) (0.19.1)
Requirement already satisfied: decorator in /usr/local/lib/python3.10/dist-packages (from ipython<9->ipympl==0.9.3->-r /content/requirements_small.txt (line 5)) (4.4.2)
Requirement already satisfied: pickleshare in /usr/local/lib/python3.10/dist-packages (from ipython<9->ipympl==0.9.3->-r /content/requirements_small.txt (line 5)) (0.7.5)
Requirement already satisfied: prompt-toolkit!=3.0.0,!=3.0.1,<3.1.0,>=2.0.0 in /usr/local/lib/python3.10/dist-packages (from ipython<9->ipympl==0.9.3->-r /content/requirements_small.txt (line 5)) (3.0.43)
Requirement already satisfied: pygments in /usr/local/lib/python3.10/dist-packages (from ipython<9->ipympl==0.9.3->-r /content/requirements_small.txt (line 5)) (2.16.1)
Requirement already satisfied: backcall in /usr/local/lib/python3.10/dist-packages (from ipython<9->ipympl==0.9.3->-r /content/requirements_small.txt (line 5)) (0.2.0)
Requirement already satisfied: pexpect>4.3 in /usr/local/lib/python3.10/dist-packages (from ipython<9->ipympl==0.9.3->-r /content/requirements_small.txt (line 5)) (4.9.0)
Requirement already satisfied: llvmlite<0.42,>=0.41.0dev0 in /usr/local/lib/python3.10/dist-packages (from numba>=0.49->umap-learn==0.5.3->-r /content/requirements_small.txt (line 21)) (0.41.1)
Requirement already satisfied: notebook>=4.4.1 in /usr/local/lib/python3.10/dist-packages (from widgetsnbextension~=3.6.0->ipywidgets==7.7.1->-r /content/requirements_small.txt (line 6)) (6.5.5)
Requirement already satisfied: soupsieve>1.2 in /usr/local/lib/python3.10/dist-packages (from beautifulsoup4->gdown==5.1.0->-r /content/requirements_small.txt (line 2)) (2.5)
Requirement already satisfied: charset-normalizer<4,>=2 in /usr/local/lib/python3.10/dist-packages (from requests[socks]->gdown==5.1.0->-r /content/requirements_small.txt (line 2)) (3.3.2)
Requirement already satisfied: idna<4,>=2.5 in /usr/local/lib/python3.10/dist-packages (from requests[socks]->gdown==5.1.0->-r /content/requirements_small.txt (line 2)) (3.6)
Requirement already satisfied: urllib3<3,>=1.21.1 in /usr/local/lib/python3.10/dist-packages (from requests[socks]->gdown==5.1.0->-r /content/requirements_small.txt (line 2)) (2.0.7)
Requirement already satisfied: certifi>=2017.4.17 in /usr/local/lib/python3.10/dist-packages (from requests[socks]->gdown==5.1.0->-r /content/requirements_small.txt (line 2)) (2024.2.2)
Requirement already satisfied: PySocks!=1.5.7,>=1.5.6 in /usr/local/lib/python3.10/dist-packages (from requests[socks]->gdown==5.1.0->-r /content/requirements_small.txt (line 2)) (1.7.1)
Requirement already satisfied: parso<0.9.0,>=0.8.3 in /usr/local/lib/python3.10/dist-packages (from jedi>=0.16->ipython<9->ipympl==0.9.3->-r /content/requirements_small.txt (line 5)) (0.8.3)
Requirement already satisfied: jinja2 in /usr/local/lib/python3.10/dist-packages (from notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets==7.7.1->-r /content/requirements_small.txt (line 6)) (3.1.3)
Requirement already satisfied: pyzmq<25,>=17 in /usr/local/lib/python3.10/dist-packages (from notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets==7.7.1->-r /content/requirements_small.txt (line 6)) (23.2.1)
Requirement already satisfied: argon2-cffi in /usr/local/lib/python3.10/dist-packages (from notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets==7.7.1->-r /content/requirements_small.txt (line 6)) (23.1.0)
Requirement already satisfied: jupyter-core>=4.6.1 in /usr/local/lib/python3.10/dist-packages (from notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets==7.7.1->-r /content/requirements_small.txt (line 6)) (5.7.1)
Requirement already satisfied: nbformat in /usr/local/lib/python3.10/dist-packages (from notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets==7.7.1->-r /content/requirements_small.txt (line 6)) (5.9.2)
Requirement already satisfied: nbconvert>=5 in /usr/local/lib/python3.10/dist-packages (from notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets==7.7.1->-r /content/requirements_small.txt (line 6)) (6.5.4)
Requirement already satisfied: nest-asyncio>=1.5 in /usr/local/lib/python3.10/dist-packages (from notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets==7.7.1->-r /content/requirements_small.txt (line 6)) (1.6.0)
Requirement already satisfied: Send2Trash>=1.8.0 in /usr/local/lib/python3.10/dist-packages (from notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets==7.7.1->-r /content/requirements_small.txt (line 6)) (1.8.2)
Requirement already satisfied: terminado>=0.8.3 in /usr/local/lib/python3.10/dist-packages (from notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets==7.7.1->-r /content/requirements_small.txt (line 6)) (0.18.0)
Requirement already satisfied: prometheus-client in /usr/local/lib/python3.10/dist-packages (from notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets==7.7.1->-r /content/requirements_small.txt (line 6)) (0.20.0)
Requirement already satisfied: nbclassic>=0.4.7 in /usr/local/lib/python3.10/dist-packages (from notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets==7.7.1->-r /content/requirements_small.txt (line 6)) (1.0.0)
Requirement already satisfied: ptyprocess>=0.5 in /usr/local/lib/python3.10/dist-packages (from pexpect>4.3->ipython<9->ipympl==0.9.3->-r /content/requirements_small.txt (line 5)) (0.7.0)
Requirement already satisfied: wcwidth in /usr/local/lib/python3.10/dist-packages (from prompt-toolkit!=3.0.0,!=3.0.1,<3.1.0,>=2.0.0->ipython<9->ipympl==0.9.3->-r /content/requirements_small.txt (line 5)) (0.2.13)
Requirement already satisfied: platformdirs>=2.5 in /usr/local/lib/python3.10/dist-packages (from jupyter-core>=4.6.1->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets==7.7.1->-r /content/requirements_small.txt (line 6)) (4.2.0)
Requirement already satisfied: jupyter-server>=1.8 in /usr/local/lib/python3.10/dist-packages (from nbclassic>=0.4.7->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets==7.7.1->-r /content/requirements_small.txt (line 6)) (1.24.0)
Requirement already satisfied: notebook-shim>=0.2.3 in /usr/local/lib/python3.10/dist-packages (from nbclassic>=0.4.7->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets==7.7.1->-r /content/requirements_small.txt (line 6)) (0.2.4)
Requirement already satisfied: lxml in /usr/local/lib/python3.10/dist-packages (from nbconvert>=5->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets==7.7.1->-r /content/requirements_small.txt (line 6)) (4.9.4)
Requirement already satisfied: bleach in /usr/local/lib/python3.10/dist-packages (from nbconvert>=5->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets==7.7.1->-r /content/requirements_small.txt (line 6)) (6.1.0)
Requirement already satisfied: defusedxml in /usr/local/lib/python3.10/dist-packages (from nbconvert>=5->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets==7.7.1->-r /content/requirements_small.txt (line 6)) (0.7.1)
Requirement already satisfied: entrypoints>=0.2.2 in /usr/local/lib/python3.10/dist-packages (from nbconvert>=5->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets==7.7.1->-r /content/requirements_small.txt (line 6)) (0.4)
Requirement already satisfied: jupyterlab-pygments in /usr/local/lib/python3.10/dist-packages (from nbconvert>=5->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets==7.7.1->-r /content/requirements_small.txt (line 6)) (0.3.0)
Requirement already satisfied: MarkupSafe>=2.0 in /usr/local/lib/python3.10/dist-packages (from nbconvert>=5->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets==7.7.1->-r /content/requirements_small.txt (line 6)) (2.1.5)
Requirement already satisfied: mistune<2,>=0.8.1 in /usr/local/lib/python3.10/dist-packages (from nbconvert>=5->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets==7.7.1->-r /content/requirements_small.txt (line 6)) (0.8.4)
Requirement already satisfied: nbclient>=0.5.0 in /usr/local/lib/python3.10/dist-packages (from nbconvert>=5->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets==7.7.1->-r /content/requirements_small.txt (line 6)) (0.9.0)
Requirement already satisfied: pandocfilters>=1.4.1 in /usr/local/lib/python3.10/dist-packages (from nbconvert>=5->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets==7.7.1->-r /content/requirements_small.txt (line 6)) (1.5.1)
Requirement already satisfied: tinycss2 in /usr/local/lib/python3.10/dist-packages (from nbconvert>=5->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets==7.7.1->-r /content/requirements_small.txt (line 6)) (1.2.1)
Requirement already satisfied: fastjsonschema in /usr/local/lib/python3.10/dist-packages (from nbformat->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets==7.7.1->-r /content/requirements_small.txt (line 6)) (2.19.1)
Requirement already satisfied: jsonschema>=2.6 in /usr/local/lib/python3.10/dist-packages (from nbformat->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets==7.7.1->-r /content/requirements_small.txt (line 6)) (4.19.2)
Requirement already satisfied: argon2-cffi-bindings in /usr/local/lib/python3.10/dist-packages (from argon2-cffi->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets==7.7.1->-r /content/requirements_small.txt (line 6)) (21.2.0)
Requirement already satisfied: attrs>=22.2.0 in /usr/local/lib/python3.10/dist-packages (from jsonschema>=2.6->nbformat->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets==7.7.1->-r /content/requirements_small.txt (line 6)) (23.2.0)
Requirement already satisfied: jsonschema-specifications>=2023.03.6 in /usr/local/lib/python3.10/dist-packages (from jsonschema>=2.6->nbformat->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets==7.7.1->-r /content/requirements_small.txt (line 6)) (2023.12.1)
Requirement already satisfied: referencing>=0.28.4 in /usr/local/lib/python3.10/dist-packages (from jsonschema>=2.6->nbformat->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets==7.7.1->-r /content/requirements_small.txt (line 6)) (0.33.0)
Requirement already satisfied: rpds-py>=0.7.1 in /usr/local/lib/python3.10/dist-packages (from jsonschema>=2.6->nbformat->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets==7.7.1->-r /content/requirements_small.txt (line 6)) (0.18.0)
Requirement already satisfied: anyio<4,>=3.1.0 in /usr/local/lib/python3.10/dist-packages (from jupyter-server>=1.8->nbclassic>=0.4.7->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets==7.7.1->-r /content/requirements_small.txt (line 6)) (3.7.1)
Requirement already satisfied: websocket-client in /usr/local/lib/python3.10/dist-packages (from jupyter-server>=1.8->nbclassic>=0.4.7->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets==7.7.1->-r /content/requirements_small.txt (line 6)) (1.7.0)
Requirement already satisfied: cffi>=1.0.1 in /usr/local/lib/python3.10/dist-packages (from argon2-cffi-bindings->argon2-cffi->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets==7.7.1->-r /content/requirements_small.txt (line 6)) (1.16.0)
Requirement already satisfied: webencodings in /usr/local/lib/python3.10/dist-packages (from bleach->nbconvert>=5->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets==7.7.1->-r /content/requirements_small.txt (line 6)) (0.5.1)
Requirement already satisfied: sniffio>=1.1 in /usr/local/lib/python3.10/dist-packages (from anyio<4,>=3.1.0->jupyter-server>=1.8->nbclassic>=0.4.7->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets==7.7.1->-r /content/requirements_small.txt (line 6)) (1.3.1)
Requirement already satisfied: pycparser in /usr/local/lib/python3.10/dist-packages (from cffi>=1.0.1->argon2-cffi-bindings->argon2-cffi->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets==7.7.1->-r /content/requirements_small.txt (line 6)) (2.21)
In [ ]:
!gdown -V
gdown 4.7.3 at /usr/local/lib/python3.10/dist-packages
In [ ]:
import catboost
assert(catboost.__version__ == '1.2.1')

Введение¶

Привет, ребятушки!

Сегодня мы с вами будем решать очень важную задачу, а именно оценивать цену подержанных автомобилей в ряде стран. Делать мы это будем с помощью различных методов градиентного бустинга. Мы с вами узнаем, что в мире существует не только sklearn, и что существуют библиотеки, облегчающие нам задачу поиска оптимальных параметров для моделей.

Внимание! Во всех заданиях в качестве целевой метрики используется MAE (средняя абсолютная ошибка). Значение MAE вычисляется как

$$ MAE = \sum_{i = 1}^N\dfrac{|a(x_i) - y_i|}{N}, $$

где $N$ - число объектов в тестовой выборке, $x_i$ - вектор признаков i-го объекта, $a(x_i)$ - предсказание на i-ом объекте, $y_i$ - значение целевого признака на i-м объекте.

Используемые библиотеки¶

В этом задании нам понадобятся три библиотеки, которыми вы ранее не пользовались в этом курсе, а именно:

XGBoost: Документация здесь.
LightGBM: Документация здесь. Также дополнительно про установку тут.
Catboost: Документация здесь. Можно найти также некоторую информацию на русском тут.
HyperOpt: Документация здесь.

**Внимание!** Вникать и подробно читать документацию к каждой библиотеке нет необходимости! Достаточно обращаться туда для нахождения примеров обучения.


Различия в методах бустинга¶

Каждая библиотека, которую мы будем сегодня использовать, имеет свой подход к обучению. Понимание этих различий выходит за рамки данного задания, но при желании можно обратиться к документации библиотек или лекциям Дьяконова.

Как правильно перебирать параметры¶

В этом ноутбуке мы будем несколько раз заниматься поиском оптимальных параметров для градиентного бустинга, перебирая задания по заданной сетке. В этом задании от вас не будет требоваться найти самые лучшие параметры, но всё равно важно правильно составлять сетку для перебора. Для этого нужно понимать суть параметров и их смысл.

**learning_rate** -- темп обучения нашего метода. Для этого метода сетка перебора должна быть логарифмической, т.е. перебирать порядковые значения (к примеру, [1e-3, 1e-2, 1e-1, 1]). В большинстве случаев достаточно перебрать значения от 1e-5 до 1.

**max_depth** -- максимальная глубина деревьев в ансамбле. Вообще говоря, эта величина зависит от числа признаков, но обычно лучше растить небольшие деревья. К примеру, библиотека CatBoost, которую мы будем исследовать сегодня, рекомендует перебирать значения до 10 (и уточняется, что обычно оптимальная глубина лежит от 6 до 10).

**subsample** -- объем выборки, использующийся для обучения отдельного дерева, лежит в интервале (0, 1]. Перебирать стоит хотя бы с шагом 0.25

**n_estimators** -- количество деревьев в ансамбле. Обычно стоит перебирать с каким-то крупным шагом (можно по логарифмической сетке). Здесь важно найти баланс между производительностью, временем обучения и качеством. Обычно нескольких тысяч деревьев бывает достаточно.

**NB!** Учтите, что в реальных задачах необходимо следить за тем, что оптимальные значения параметров не попадают на границы интервалов, т.е. что вы нашли хотя бы локальный минимум. Если вы перебрали значения параметра от 1 до 10 и оказалось, что 10 - оптимальное значение, значит следует перебрать и бОльшие числа, чтобы убедиться, что качество не улучшается дальше (или по крайней мере убедиться, что рост качества сильно замедляется и на сильное улучшение рассчитывать не стоит.

Подготовка датасета¶

Все библиотеки, используемые сегодня, мы будем проверять на одних и тех же параметрах:

n_estimators=1000, max_depth=5, learning_rate=0.1

Таким образом мы устанавливаем, соответственно, число деревьев в ансамбле равным 1000, ограничиваем максимальную глубину деревьев 5 и устанавливаем темп обучения равным 0.1. Создадим сразу словарь, чтобы передавать эти параметры создаваемым регрессорам (если вдруг не знали, словарь можно передавать как параметры, поставив перед ним **).

Эти параметры мы вынесем в отдельную переменную test_parameters.

При желании можно почитать про этот датасет на платформе kaggle: ссылка на данные. Не скачивайте датасет из kaggle для выполнения ноутбука, поскольку его могут изменить. Нас интересует файл dataframe_YesIndex_YesHeader_C.csv, поскольку он уже хорошо предобработан (хотя, конечно, датасаентисты должны сами уметь это делать, но ладно). Давайте попробуем загрузить датасет в память и посмотреть, как он выглядит.

При работе в google colab для скачивания датасета достаточно запустить следующую ячейку.

При работе с ноутбуком на локальном компьютере Вы можете скачать файл по этой ссылке и чуть ниже заменить /content/dataframe_YesIndex_YesHeader_C.csv (в строке с read_csv) на ваш локальный путь до файла.

In [ ]:
# при локальном выполнении запускать эту ячейку НЕ НАДО
!gdown 1gdDv2kTCEkF3ia1vvbvRFJM0YfqmPplb
Downloading...
From: https://drive.google.com/uc?id=1gdDv2kTCEkF3ia1vvbvRFJM0YfqmPplb
To: /content/dataframe_YesIndex_YesHeader_C.csv
100% 568k/568k [00:00<00:00, 24.9MB/s]
In [ ]:
%matplotlib inline
from sklearn.ensemble import GradientBoostingRegressor
from sklearn.model_selection import train_test_split, GridSearchCV, cross_val_score
from sklearn.metrics import mean_absolute_error, make_scorer

from hyperopt import hp, tpe, Trials
from hyperopt.fmin import fmin
from hyperopt.pyll import scope

from xgboost import XGBRegressor

from lightgbm import LGBMRegressor

from catboost import CatBoostRegressor

import matplotlib.pyplot as plt

import pandas as pd

import numpy as np

import time
In [ ]:
test_parameters = {"n_estimators": 1000, "max_depth": 5, "learning_rate":0.1, "subsample": 1.0}

df = pd.read_csv('/content/dataframe_YesIndex_YesHeader_C.csv', index_col=0)
df.head()
Out[ ]:
Engine Capacity Cylinders Drive Type Fuel Tank Capacity Fuel Economy Fuel Type Horsepower Torque Transmission Top Speed ... Acceleration Length Width Height Wheelbase Trunk Capacity name price currency Country
0 1.2 3 0 42.0 4.9 0 76 100.0 0 170 ... 14.0 4.245 1.670 1.515 2.550 450.0 Mitsubishi Attrage 2021 1.2 GLX (Base) 34099.0 0 0
1 1.2 3 0 42.0 4.9 0 76 100.0 0 170 ... 14.0 4.245 1.670 1.515 2.550 450.0 Mitsubishi Attrage 2021 1.2 GLX (Base) 34099.0 0 0
2 1.4 4 0 45.0 6.3 0 75 118.0 1 156 ... 16.0 3.864 1.716 1.721 2.513 2800.0 Fiat Fiorino 2021 1.4L Standard 41250.0 0 0
3 1.6 4 0 50.0 6.4 0 102 145.0 0 180 ... 11.0 4.354 1.994 1.529 2.635 510.0 Renault Symbol 2021 1.6L PE 44930.0 0 0
4 1.5 4 0 48.0 5.8 0 112 150.0 0 170 ... 10.9 4.314 1.809 1.624 2.585 448.0 MG ZS 2021 1.5L STD 57787.0 0 0

5 rows × 21 columns

**Задание 0 (без проверки, 0 баллов)**¶

Посмотрите на цены автомобилей. Попробуйте понять, написаны они в одной валюте или нет. Если нет -- будут ли у нас серьезные проблемы при использовании деревьев? Стоит ли нам что-то сделать для того, чтобы нивелировать эту проблему?

Выводы: В результате небольшого исследования с использованием google и различных автомобильных аукционов можно сделать вывод о том, что цена на автомобили написаны в одной валюте, вероятнее всего в AED. Ситуация, когда в данных представлены стоимости машин в различных валютах однозначно приведет к трудностям при обучении и как следствие при использовании нашей модели. Причины у этого следующие: 1. Различная стоимость валют 2. Влияние колебаний валютного курса 3. Нарушается предположение о единности формата данных, что приводит к неправильному обучению модели Чтобы решить эту проблему стоит привести все цены к единной валюте (Как? Неизвестно какая цена в какой валюте), можно добавить дополнительный признак с указанием валют.

В глаза бросаются две проблемы: у нас имеется информация о производителе автомобиля, скрытая в текстовой переменной модели автомобиля (нет отдельного признака). Также имеются некоторые категориальные переменные. Со всем этим безобразием надо что-то сделать.

**Задание 1 (кросс-проверка, 2 балла)**¶

Данные: датасет со стоимостью подержанных автомобилей
Цели: В данном задании следует выполнить следующие пункты (выполнять можно в любом порядке)

  1. Изучить датасет, проверить наличие пропусков. Под пропусками подразумевается значение N/A вместо признака. При необходимости заменить их на среднее значение признака.
  2. Добавить столбец brand с информацией о производителе автомобиля (для простоты можно взять первое слово в названии модели).
  3. Решить, какие признаки Вы считаете категориальными.
  4. Создать датасет А, в котором выбранные категориальные признаки установлены как категориальные. Для этого необходимо создать вектор целевых значений Y (столбец цен автомобилей) и матрицу признаков X, в которой все категориальные переменные помечены как .astype('category'). Дополнительно стоит создать список с названиями и индексами столбцов категориальных переменных (поможет в будущем).
  5. Создать датасет B без категориальных признаков. Для этого необходимо просто удалить из матрицы признаков все категориальные переменные.
  6. Создать датасет C, в котором выбранные категориальные признаки закодированы через one-hot encoding. Для этого необходимо из матрицы признаков удалить выбранные категориальные переменные, а затем добавить новые признаки, соответствующие one-hot encoding этих категориальных переменных (со всей этой магией поможет простая функция pd.get_dummies).
  7. Разбить датасеты на тренировочное и тестовое множества, используя train_test_split(X, y, test_size=0.25, random_state=0) (зафиксировав random_seed мы получим одинаковое разбиение на обучение/тест для всех трёх выборок).
In [ ]:
datasets = {'A' : None, 'B': None, 'C': None}
res = []
for col in df.columns:
  if True in pd.unique(df[col].isna()):
    res.append(col)
print(res)
[]

Пропусков не нашлось

In [ ]:
brand_list = [str(name).split()[0] for name in df['name']]
df['brand'] = brand_list
df.head()
Out[ ]:
Engine Capacity Cylinders Drive Type Fuel Tank Capacity Fuel Economy Fuel Type Horsepower Torque Transmission Top Speed ... Length Width Height Wheelbase Trunk Capacity name price currency Country brand
0 1.2 3 0 42.0 4.9 0 76 100.0 0 170 ... 4.245 1.670 1.515 2.550 450.0 Mitsubishi Attrage 2021 1.2 GLX (Base) 34099.0 0 0 Mitsubishi
1 1.2 3 0 42.0 4.9 0 76 100.0 0 170 ... 4.245 1.670 1.515 2.550 450.0 Mitsubishi Attrage 2021 1.2 GLX (Base) 34099.0 0 0 Mitsubishi
2 1.4 4 0 45.0 6.3 0 75 118.0 1 156 ... 3.864 1.716 1.721 2.513 2800.0 Fiat Fiorino 2021 1.4L Standard 41250.0 0 0 Fiat
3 1.6 4 0 50.0 6.4 0 102 145.0 0 180 ... 4.354 1.994 1.529 2.635 510.0 Renault Symbol 2021 1.6L PE 44930.0 0 0 Renault
4 1.5 4 0 48.0 5.8 0 112 150.0 0 170 ... 4.314 1.809 1.624 2.585 448.0 MG ZS 2021 1.5L STD 57787.0 0 0 MG

5 rows × 22 columns

In [ ]:
for col in df.columns:
  print(col, np.unique(df[col]))
Engine Capacity [0.  1.  1.1 1.2 1.3 1.4 1.5 1.6 1.8 1.9 2.  2.2 2.3 2.4 2.5 2.7 2.8 2.9
 3.  3.2 3.3 3.4 3.5 3.6 3.7 3.8 3.9 4.  4.2 4.3 4.4 4.5 4.6 4.7 4.8 5.
 5.2 5.3 5.5 5.6 5.7 5.9 6.  6.2 6.3 6.4 6.5 6.6 6.7 6.8 8. ]
Cylinders [ 3  4  5  6  8 10 12 16]
Drive Type [0 1 2]
Fuel Tank Capacity [ 32.   35.   37.   40.   41.   42.   43.   44.   45.   46.   47.   48.
  50.   51.   52.   53.   54.   55.   56.   57.   58.   59.   60.   61.
  61.3  61.7  62.   62.5  63.   64.   65.   66.   67.   68.   68.5  69.
  69.6  70.   71.   72.   73.   74.   75.   76.   77.   78.   80.   82.
  83.   84.   85.   86.   87.   88.   88.5  89.   90.   90.5  91.   93.
  95.   96.   98.  100.  104.  105.  106.  107.  117.  135.  136.  138.
 140.  150.  159. ]
Fuel Economy [ 2.5   2.8   2.9   3.    3.1   3.3   3.4   3.7   3.8   4.    4.1   4.3
  4.4   4.5   4.6   4.7   4.8   4.9   5.    5.1   5.2   5.3   5.4   5.5
  5.6   5.7   5.8   5.88  5.9   6.    6.1   6.2   6.3   6.4   6.5   6.6
  6.7   6.8   6.9   7.    7.1   7.2   7.3   7.4   7.5   7.6   7.7   7.8
  7.9   8.    8.1   8.2   8.3   8.4   8.5   8.6   8.7   8.8   8.9   9.
  9.1   9.2   9.3   9.4   9.5   9.6   9.7   9.8   9.9  10.   10.1  10.2
 10.3  10.4  10.5  10.6  10.7  10.8  10.9  11.   11.1  11.2  11.3  11.4
 11.5  11.6  11.7  11.8  11.9  12.   12.1  12.2  12.3  12.4  12.5  12.6
 12.7  12.8  12.9  13.   13.1  13.2  13.3  13.4  13.5  13.6  13.7  13.8
 14.   14.1  14.2  14.3  14.4  14.5  14.6  14.7  14.8  14.9  15.   15.2
 15.5  15.6  15.7  15.8  16.   16.2  16.7  16.8  16.9  17.2  18.   19.
 19.7  22.5 ]
Fuel Type [0 1 2]
Horsepower [  67   75   76   77   82   83   84   86   89   90   91   92   94   98
   99  100  102  103  104  105  106  107  108  109  110  111  112  113
  114  115  116  118  120  121  122  123  125  127  128  130  131  132
  133  134  135  136  139  140  145  147  148  150  152  153  154  155
  156  158  159  160  161  163  164  165  167  168  169  170  171  172
  173  174  175  176  177  178  180  181  182  184  185  187  188  189
  190  192  197  198  200  202  203  204  205  208  210  211  212  215
  217  218  219  220  224  225  226  227  230  231  232  235  236  240
  241  243  245  246  247  248  250  251  252  254  255  257  258  265
  268  270  271  272  275  276  277  280  283  284  285  286  288  290
  292  295  296  297  298  299  300  301  304  305  306  308  310  311
  312  313  314  315  316  320  325  326  328  329  330  333  335  338
  340  341  350  354  355  360  362  363  365  367  370  375  377  380
  381  382  385  390  394  395  397  400  401  402  404  405  407  408
  410  411  415  416  420  421  428  430  431  435  438  440  442  450
  453  455  460  462  464  465  469  470  471  475  476  485  490  500
  503  505  510  520  521  525  526  530  540  542  544  545  550  557
  558  560  562  563  565  567  568  570  571  572  573  575  577  580
  585  590  592  593  600  605  610  612  624  625  626  630  635  640
  650  670  680  690  707  740  770  797  887 1500 5050]
Torque [  87.   90.  100.  102.  113.  114.  118.  120.  121.  122.  123.  127.
  130.  131.  132.  133.  134.  135.  136.  138.  139.  140.  141.  142.
  143.  145.  146.  148.  149.  150.  151.  152.  153.  154.  155.  156.
  157.  160.  161.  163.  170.  174.  175.  179.  180.  182.  185.  187.
  192.  193.  194.  195.  196.  197.  198.  200.  205.  207.  210.  213.
  215.  220.  221.  222.  225.  226.  227.  230.  231.  232.  233.  234.
  235.  237.  240.  241.  243.  244.  245.  246.  249.  250.  251.  258.
  259.  260.  265.  270.  275.  280.  285.  290.  292.  294.  300.  303.
  306.  310.  316.  317.  320.  324.  326.  327.  330.  335.  336.  338.
  339.  340.  342.  345.  346.  350.  352.  353.  355.  356.  358.  360.
  361.  362.  363.  365.  366.  369.  370.  375.  376.  377.  378.  379.
  380.  381.  383.  385.  386.  389.  390.  395.  397.  400.  407.  410.
  413.  420.  430.  434.  438.  439.  440.  450.  451.  460.  465.  470.
  474.  475.  480.  490.  493.  495.  500.  505.  510.  515.  518.  520.
  527.  530.  535.  536.  540.  542.  544.  550.  555.  556.  560.  569.
  570.  575.  580.  582.  583.  588.  590.  600.  603.  610.  614.  615.
  620.  623.  624.  625.  629.  630.  637.  645.  650.  652.  660.  675.
  680.  685.  690.  691.  697.  700.  710.  720.  730.  750.  755.  760.
  770.  800.  814.  820.  830.  840.  850.  855.  870.  875.  881.  900.
  959. 1000. 1020. 1100. 1280. 1600.]
Transmission [0 1 2]
Top Speed [140 145 150 155 156 158 160 161 162 165 167 169 170 172 173 174 175 177
 178 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196
 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 215
 216 217 218 220 222 224 225 226 227 228 229 230 232 233 234 235 236 237
 238 240 241 242 243 244 245 246 248 249 250 251 253 258 259 260 261 263
 264 265 266 267 270 272 275 278 279 280 281 283 285 286 288 289 290 291
 292 293 295 296 299 300 301 302 303 304 305 306 307 308 309 310 314 315
 316 317 318 320 322 323 325 327 328 330 331 333 335 343 345 350 420]
Seating Capacity [2 3 4 5 6 7 8 9]
Acceleration [ 2.4  2.8  3.   3.2  3.3  3.4  3.5  3.6  3.7  3.8  3.9  4.   4.1  4.2
  4.3  4.4  4.5  4.6  4.7  4.8  4.9  5.   5.1  5.2  5.3  5.4  5.5  5.6
  5.7  5.8  5.9  6.   6.1  6.2  6.3  6.4  6.5  6.6  6.7  6.8  6.9  7.
  7.1  7.2  7.3  7.4  7.5  7.6  7.7  7.8  7.9  8.   8.1  8.2  8.3  8.4
  8.5  8.6  8.7  8.8  8.9  9.   9.1  9.2  9.3  9.4  9.5  9.6  9.7  9.8
  9.9 10.  10.1 10.2 10.3 10.4 10.5 10.6 10.7 10.8 10.9 11.  11.1 11.2
 11.3 11.4 11.5 11.6 11.7 11.8 11.9 12.  12.1 12.2 12.3 12.4 12.5 12.6
 12.7 12.8 12.9 13.  13.1 13.2 13.4 13.5 13.6 13.7 13.9 14.  14.2 14.5
 15.  15.1 15.2 15.4 15.5 16.  16.2 17.5 17.9]
Length [3.500e+00 3.546e+00 3.585e+00 3.595e+00 3.600e+00 3.636e+00 3.645e+00
 3.650e+00 3.657e+00 3.660e+00 3.665e+00 3.700e+00 3.765e+00 3.780e+00
 3.795e+00 3.796e+00 3.821e+00 3.840e+00 3.850e+00 3.864e+00 3.874e+00
 3.915e+00 3.941e+00 3.948e+00 3.954e+00 3.962e+00 3.969e+00 3.973e+00
 3.982e+00 3.989e+00 3.992e+00 3.995e+00 4.000e+00 4.005e+00 4.021e+00
 4.039e+00 4.054e+00 4.059e+00 4.060e+00 4.061e+00 4.062e+00 4.065e+00
 4.096e+00 4.109e+00 4.114e+00 4.115e+00 4.124e+00 4.133e+00 4.134e+00
 4.145e+00 4.155e+00 4.160e+00 4.165e+00 4.173e+00 4.175e+00 4.177e+00
 4.190e+00 4.191e+00 4.202e+00 4.220e+00 4.223e+00 4.225e+00 4.230e+00
 4.234e+00 4.236e+00 4.237e+00 4.239e+00 4.240e+00 4.244e+00 4.245e+00
 4.248e+00 4.250e+00 4.253e+00 4.255e+00 4.256e+00 4.257e+00 4.258e+00
 4.263e+00 4.265e+00 4.270e+00 4.275e+00 4.278e+00 4.280e+00 4.287e+00
 4.295e+00 4.299e+00 4.300e+00 4.310e+00 4.314e+00 4.319e+00 4.320e+00
 4.324e+00 4.329e+00 4.335e+00 4.341e+00 4.342e+00 4.343e+00 4.345e+00
 4.348e+00 4.350e+00 4.351e+00 4.354e+00 4.355e+00 4.358e+00 4.361e+00
 4.362e+00 4.365e+00 4.367e+00 4.370e+00 4.374e+00 4.379e+00 4.380e+00
 4.382e+00 4.384e+00 4.385e+00 4.388e+00 4.391e+00 4.394e+00 4.395e+00
 4.397e+00 4.399e+00 4.405e+00 4.410e+00 4.420e+00 4.424e+00 4.425e+00
 4.427e+00 4.430e+00 4.432e+00 4.435e+00 4.440e+00 4.442e+00 4.445e+00
 4.447e+00 4.450e+00 4.454e+00 4.455e+00 4.456e+00 4.458e+00 4.460e+00
 4.461e+00 4.463e+00 4.465e+00 4.466e+00 4.469e+00 4.470e+00 4.475e+00
 4.477e+00 4.479e+00 4.480e+00 4.482e+00 4.483e+00 4.485e+00 4.486e+00
 4.487e+00 4.490e+00 4.491e+00 4.500e+00 4.505e+00 4.506e+00 4.510e+00
 4.519e+00 4.524e+00 4.525e+00 4.527e+00 4.528e+00 4.529e+00 4.530e+00
 4.532e+00 4.533e+00 4.534e+00 4.540e+00 4.544e+00 4.545e+00 4.550e+00
 4.555e+00 4.556e+00 4.568e+00 4.569e+00 4.570e+00 4.572e+00 4.575e+00
 4.580e+00 4.583e+00 4.585e+00 4.586e+00 4.590e+00 4.594e+00 4.595e+00
 4.599e+00 4.600e+00 4.610e+00 4.615e+00 4.617e+00 4.624e+00 4.625e+00
 4.626e+00 4.630e+00 4.631e+00 4.632e+00 4.633e+00 4.635e+00 4.638e+00
 4.640e+00 4.641e+00 4.643e+00 4.644e+00 4.649e+00 4.650e+00 4.655e+00
 4.656e+00 4.659e+00 4.660e+00 4.663e+00 4.665e+00 4.666e+00 4.670e+00
 4.671e+00 4.672e+00 4.673e+00 4.674e+00 4.680e+00 4.686e+00 4.688e+00
 4.690e+00 4.691e+00 4.692e+00 4.693e+00 4.694e+00 4.695e+00 4.696e+00
 4.697e+00 4.698e+00 4.703e+00 4.704e+00 4.705e+00 4.708e+00 4.709e+00
 4.710e+00 4.712e+00 4.715e+00 4.716e+00 4.719e+00 4.723e+00 4.726e+00
 4.730e+00 4.732e+00 4.733e+00 4.735e+00 4.739e+00 4.742e+00 4.744e+00
 4.745e+00 4.746e+00 4.750e+00 4.752e+00 4.753e+00 4.758e+00 4.759e+00
 4.760e+00 4.779e+00 4.780e+00 4.783e+00 4.784e+00 4.785e+00 4.790e+00
 4.792e+00 4.795e+00 4.797e+00 4.800e+00 4.801e+00 4.803e+00 4.805e+00
 4.806e+00 4.810e+00 4.813e+00 4.819e+00 4.820e+00 4.821e+00 4.822e+00
 4.825e+00 4.826e+00 4.828e+00 4.829e+00 4.830e+00 4.834e+00 4.843e+00
 4.846e+00 4.848e+00 4.849e+00 4.850e+00 4.851e+00 4.855e+00 4.856e+00
 4.859e+00 4.861e+00 4.865e+00 4.869e+00 4.871e+00 4.872e+00 4.879e+00
 4.880e+00 4.881e+00 4.884e+00 4.885e+00 4.890e+00 4.894e+00 4.897e+00
 4.898e+00 4.900e+00 4.905e+00 4.915e+00 4.917e+00 4.918e+00 4.922e+00
 4.923e+00 4.924e+00 4.925e+00 4.926e+00 4.930e+00 4.931e+00 4.936e+00
 4.939e+00 4.945e+00 4.950e+00 4.954e+00 4.956e+00 4.961e+00 4.962e+00
 4.963e+00 4.966e+00 4.969e+00 4.970e+00 4.971e+00 4.974e+00 4.980e+00
 4.986e+00 4.988e+00 4.989e+00 4.990e+00 4.993e+00 4.996e+00 4.998e+00
 4.999e+00 5.000e+00 5.001e+00 5.003e+00 5.005e+00 5.006e+00 5.008e+00
 5.011e+00 5.012e+00 5.018e+00 5.019e+00 5.020e+00 5.027e+00 5.032e+00
 5.036e+00 5.037e+00 5.040e+00 5.044e+00 5.049e+00 5.051e+00 5.052e+00
 5.053e+00 5.065e+00 5.070e+00 5.075e+00 5.080e+00 5.088e+00 5.090e+00
 5.091e+00 5.092e+00 5.094e+00 5.095e+00 5.100e+00 5.110e+00 5.112e+00
 5.113e+00 5.115e+00 5.116e+00 5.120e+00 5.126e+00 5.127e+00 5.130e+00
 5.131e+00 5.140e+00 5.141e+00 5.147e+00 5.153e+00 5.165e+00 5.168e+00
 5.170e+00 5.171e+00 5.172e+00 5.174e+00 5.179e+00 5.182e+00 5.183e+00
 5.189e+00 5.199e+00 5.200e+00 5.205e+00 5.207e+00 5.210e+00 5.219e+00
 5.222e+00 5.227e+00 5.235e+00 5.238e+00 5.246e+00 5.247e+00 5.252e+00
 5.255e+00 5.262e+00 5.265e+00 5.271e+00 5.285e+00 5.293e+00 5.295e+00
 5.302e+00 5.309e+00 5.315e+00 5.316e+00 5.325e+00 5.330e+00 5.335e+00
 5.340e+00 5.351e+00 5.362e+00 5.380e+00 5.399e+00 5.413e+00 5.462e+00
 5.569e+00 5.575e+00 5.585e+00 5.612e+00 5.636e+00 5.672e+00 5.697e+00
 5.762e+00 5.825e+00 5.890e+00 5.895e+00 5.915e+00 5.916e+00 6.035e+00
 6.128e+00 6.322e+00 6.352e+00 6.363e+00 6.560e+00 6.758e+00 4.694e+03
 4.795e+03]
Width [1.595e+00 1.597e+00 1.600e+00 1.627e+00 1.645e+00 1.647e+00 1.655e+00
 1.660e+00 1.665e+00 1.670e+00 1.675e+00 1.680e+00 1.686e+00 1.692e+00
 1.693e+00 1.695e+00 1.699e+00 1.700e+00 1.705e+00 1.706e+00 1.715e+00
 1.716e+00 1.720e+00 1.725e+00 1.727e+00 1.728e+00 1.729e+00 1.730e+00
 1.732e+00 1.735e+00 1.736e+00 1.739e+00 1.740e+00 1.745e+00 1.746e+00
 1.748e+00 1.755e+00 1.760e+00 1.762e+00 1.765e+00 1.774e+00 1.775e+00
 1.776e+00 1.777e+00 1.778e+00 1.780e+00 1.781e+00 1.785e+00 1.786e+00
 1.789e+00 1.790e+00 1.792e+00 1.794e+00 1.795e+00 1.796e+00 1.798e+00
 1.799e+00 1.800e+00 1.801e+00 1.802e+00 1.804e+00 1.805e+00 1.806e+00
 1.808e+00 1.809e+00 1.810e+00 1.811e+00 1.814e+00 1.815e+00 1.816e+00
 1.820e+00 1.821e+00 1.822e+00 1.823e+00 1.825e+00 1.827e+00 1.828e+00
 1.829e+00 1.830e+00 1.831e+00 1.833e+00 1.834e+00 1.837e+00 1.838e+00
 1.839e+00 1.840e+00 1.841e+00 1.842e+00 1.843e+00 1.844e+00 1.845e+00
 1.846e+00 1.850e+00 1.852e+00 1.854e+00 1.855e+00 1.860e+00 1.861e+00
 1.863e+00 1.864e+00 1.865e+00 1.866e+00 1.868e+00 1.869e+00 1.870e+00
 1.871e+00 1.874e+00 1.875e+00 1.877e+00 1.879e+00 1.880e+00 1.882e+00
 1.885e+00 1.886e+00 1.888e+00 1.890e+00 1.891e+00 1.893e+00 1.894e+00
 1.895e+00 1.897e+00 1.899e+00 1.900e+00 1.902e+00 1.903e+00 1.905e+00
 1.906e+00 1.907e+00 1.910e+00 1.911e+00 1.912e+00 1.915e+00 1.918e+00
 1.920e+00 1.923e+00 1.925e+00 1.926e+00 1.927e+00 1.928e+00 1.929e+00
 1.930e+00 1.935e+00 1.937e+00 1.938e+00 1.939e+00 1.940e+00 1.941e+00
 1.942e+00 1.943e+00 1.945e+00 1.947e+00 1.948e+00 1.950e+00 1.951e+00
 1.952e+00 1.954e+00 1.956e+00 1.958e+00 1.960e+00 1.966e+00 1.967e+00
 1.969e+00 1.975e+00 1.976e+00 1.978e+00 1.980e+00 1.981e+00 1.983e+00
 1.984e+00 1.987e+00 1.988e+00 1.989e+00 1.990e+00 1.994e+00 1.995e+00
 1.996e+00 1.998e+00 2.004e+00 2.006e+00 2.008e+00 2.009e+00 2.011e+00
 2.012e+00 2.014e+00 2.016e+00 2.017e+00 2.018e+00 2.019e+00 2.020e+00
 2.022e+00 2.029e+00 2.030e+00 2.032e+00 2.037e+00 2.038e+00 2.039e+00
 2.040e+00 2.042e+00 2.044e+00 2.045e+00 2.047e+00 2.050e+00 2.052e+00
 2.056e+00 2.057e+00 2.060e+00 2.063e+00 2.065e+00 2.067e+00 2.069e+00
 2.070e+00 2.073e+00 2.077e+00 2.078e+00 2.079e+00 2.080e+00 2.084e+00
 2.090e+00 2.091e+00 2.093e+00 2.095e+00 2.098e+00 2.099e+00 2.100e+00
 2.105e+00 2.106e+00 2.111e+00 2.116e+00 2.121e+00 2.123e+00 2.139e+00
 2.140e+00 2.141e+00 2.142e+00 2.160e+00 2.172e+00 2.177e+00 2.179e+00
 2.200e+00 2.212e+00 2.222e+00 2.227e+00 2.332e+00 2.438e+00 2.459e+00
 2.463e+00 1.848e+03 1.864e+03 2.179e+03 2.292e+03]
Height [1.136e+00 1.167e+00 1.183e+00 1.201e+00 1.204e+00 1.211e+00 1.212e+00
 1.213e+00 1.226e+00 1.229e+00 1.230e+00 1.233e+00 1.244e+00 1.246e+00
 1.250e+00 1.258e+00 1.259e+00 1.260e+00 1.262e+00 1.269e+00 1.273e+00
 1.276e+00 1.279e+00 1.280e+00 1.281e+00 1.282e+00 1.284e+00 1.285e+00
 1.291e+00 1.292e+00 1.294e+00 1.295e+00 1.296e+00 1.298e+00 1.299e+00
 1.300e+00 1.301e+00 1.304e+00 1.308e+00 1.309e+00 1.310e+00 1.311e+00
 1.315e+00 1.318e+00 1.319e+00 1.320e+00 1.321e+00 1.322e+00 1.325e+00
 1.340e+00 1.343e+00 1.344e+00 1.346e+00 1.348e+00 1.350e+00 1.353e+00
 1.355e+00 1.359e+00 1.360e+00 1.365e+00 1.368e+00 1.370e+00 1.371e+00
 1.374e+00 1.377e+00 1.382e+00 1.383e+00 1.384e+00 1.386e+00 1.389e+00
 1.390e+00 1.391e+00 1.392e+00 1.393e+00 1.394e+00 1.395e+00 1.397e+00
 1.398e+00 1.399e+00 1.400e+00 1.403e+00 1.404e+00 1.405e+00 1.410e+00
 1.411e+00 1.413e+00 1.414e+00 1.415e+00 1.416e+00 1.417e+00 1.418e+00
 1.419e+00 1.420e+00 1.421e+00 1.422e+00 1.423e+00 1.424e+00 1.425e+00
 1.426e+00 1.427e+00 1.428e+00 1.429e+00 1.430e+00 1.432e+00 1.433e+00
 1.434e+00 1.435e+00 1.438e+00 1.440e+00 1.441e+00 1.442e+00 1.443e+00
 1.444e+00 1.445e+00 1.447e+00 1.448e+00 1.450e+00 1.452e+00 1.453e+00
 1.455e+00 1.456e+00 1.457e+00 1.458e+00 1.459e+00 1.460e+00 1.461e+00
 1.462e+00 1.463e+00 1.465e+00 1.466e+00 1.467e+00 1.468e+00 1.469e+00
 1.470e+00 1.471e+00 1.472e+00 1.473e+00 1.474e+00 1.475e+00 1.476e+00
 1.478e+00 1.479e+00 1.480e+00 1.481e+00 1.482e+00 1.483e+00 1.484e+00
 1.485e+00 1.486e+00 1.487e+00 1.488e+00 1.490e+00 1.492e+00 1.493e+00
 1.494e+00 1.495e+00 1.496e+00 1.497e+00 1.498e+00 1.499e+00 1.500e+00
 1.501e+00 1.502e+00 1.505e+00 1.507e+00 1.508e+00 1.513e+00 1.515e+00
 1.516e+00 1.517e+00 1.518e+00 1.520e+00 1.521e+00 1.523e+00 1.525e+00
 1.527e+00 1.529e+00 1.530e+00 1.535e+00 1.538e+00 1.540e+00 1.541e+00
 1.545e+00 1.550e+00 1.557e+00 1.559e+00 1.560e+00 1.565e+00 1.566e+00
 1.586e+00 1.590e+00 1.595e+00 1.598e+00 1.600e+00 1.602e+00 1.605e+00
 1.608e+00 1.610e+00 1.613e+00 1.615e+00 1.620e+00 1.621e+00 1.624e+00
 1.625e+00 1.630e+00 1.632e+00 1.638e+00 1.639e+00 1.640e+00 1.645e+00
 1.646e+00 1.647e+00 1.649e+00 1.650e+00 1.652e+00 1.653e+00 1.655e+00
 1.658e+00 1.659e+00 1.660e+00 1.661e+00 1.665e+00 1.666e+00 1.667e+00
 1.669e+00 1.670e+00 1.673e+00 1.674e+00 1.675e+00 1.676e+00 1.679e+00
 1.680e+00 1.681e+00 1.684e+00 1.685e+00 1.686e+00 1.688e+00 1.690e+00
 1.691e+00 1.693e+00 1.694e+00 1.695e+00 1.696e+00 1.700e+00 1.701e+00
 1.705e+00 1.707e+00 1.708e+00 1.709e+00 1.710e+00 1.715e+00 1.716e+00
 1.719e+00 1.721e+00 1.722e+00 1.724e+00 1.725e+00 1.727e+00 1.730e+00
 1.740e+00 1.741e+00 1.742e+00 1.745e+00 1.750e+00 1.765e+00 1.767e+00
 1.770e+00 1.775e+00 1.777e+00 1.778e+00 1.780e+00 1.785e+00 1.792e+00
 1.794e+00 1.795e+00 1.796e+00 1.797e+00 1.800e+00 1.801e+00 1.802e+00
 1.810e+00 1.813e+00 1.815e+00 1.816e+00 1.822e+00 1.825e+00 1.830e+00
 1.834e+00 1.835e+00 1.842e+00 1.845e+00 1.846e+00 1.847e+00 1.850e+00
 1.852e+00 1.855e+00 1.860e+00 1.861e+00 1.868e+00 1.869e+00 1.870e+00
 1.880e+00 1.888e+00 1.889e+00 1.890e+00 1.900e+00 1.905e+00 1.910e+00
 1.915e+00 1.918e+00 1.920e+00 1.925e+00 1.927e+00 1.928e+00 1.930e+00
 1.932e+00 1.933e+00 1.940e+00 1.941e+00 1.945e+00 1.948e+00 1.955e+00
 1.965e+00 1.969e+00 1.971e+00 1.972e+00 1.980e+00 1.989e+00 1.990e+00
 1.991e+00 2.024e+00 2.027e+00 2.123e+00 2.254e+00 2.280e+00 2.285e+00
 2.760e+00 2.778e+00 2.796e+00 1.465e+03 1.735e+03]
Wheelbase [2.250e+00 2.300e+00 2.310e+00 2.360e+00 2.380e+00 2.385e+00 2.400e+00
 2.423e+00 2.425e+00 2.430e+00 2.435e+00 2.440e+00 2.450e+00 2.457e+00
 2.459e+00 2.464e+00 2.465e+00 2.466e+00 2.469e+00 2.470e+00 2.475e+00
 2.484e+00 2.489e+00 2.495e+00 2.496e+00 2.500e+00 2.502e+00 2.505e+00
 2.510e+00 2.513e+00 2.519e+00 2.520e+00 2.525e+00 2.537e+00 2.538e+00
 2.550e+00 2.552e+00 2.555e+00 2.560e+00 2.564e+00 2.567e+00 2.570e+00
 2.575e+00 2.578e+00 2.580e+00 2.585e+00 2.587e+00 2.590e+00 2.596e+00
 2.600e+00 2.601e+00 2.602e+00 2.603e+00 2.605e+00 2.608e+00 2.610e+00
 2.612e+00 2.620e+00 2.622e+00 2.625e+00 2.626e+00 2.630e+00 2.631e+00
 2.634e+00 2.635e+00 2.636e+00 2.637e+00 2.640e+00 2.649e+00 2.650e+00
 2.651e+00 2.652e+00 2.660e+00 2.661e+00 2.662e+00 2.665e+00 2.670e+00
 2.675e+00 2.676e+00 2.680e+00 2.681e+00 2.685e+00 2.686e+00 2.690e+00
 2.693e+00 2.695e+00 2.699e+00 2.700e+00 2.702e+00 2.704e+00 2.705e+00
 2.710e+00 2.711e+00 2.718e+00 2.720e+00 2.725e+00 2.727e+00 2.728e+00
 2.730e+00 2.731e+00 2.737e+00 2.740e+00 2.741e+00 2.743e+00 2.745e+00
 2.746e+00 2.750e+00 2.751e+00 2.755e+00 2.760e+00 2.761e+00 2.764e+00
 2.765e+00 2.766e+00 2.770e+00 2.775e+00 2.776e+00 2.780e+00 2.790e+00
 2.791e+00 2.799e+00 2.800e+00 2.804e+00 2.805e+00 2.807e+00 2.808e+00
 2.810e+00 2.811e+00 2.812e+00 2.813e+00 2.817e+00 2.818e+00 2.820e+00
 2.824e+00 2.825e+00 2.829e+00 2.830e+00 2.835e+00 2.837e+00 2.840e+00
 2.841e+00 2.842e+00 2.845e+00 2.849e+00 2.850e+00 2.851e+00 2.854e+00
 2.855e+00 2.857e+00 2.858e+00 2.860e+00 2.864e+00 2.865e+00 2.866e+00
 2.868e+00 2.870e+00 2.873e+00 2.874e+00 2.885e+00 2.895e+00 2.900e+00
 2.905e+00 2.907e+00 2.908e+00 2.909e+00 2.911e+00 2.914e+00 2.915e+00
 2.916e+00 2.922e+00 2.923e+00 2.924e+00 2.930e+00 2.938e+00 2.939e+00
 2.941e+00 2.942e+00 2.945e+00 2.946e+00 2.950e+00 2.951e+00 2.960e+00
 2.964e+00 2.969e+00 2.970e+00 2.975e+00 2.979e+00 2.982e+00 2.984e+00
 2.985e+00 2.989e+00 2.990e+00 2.994e+00 2.995e+00 2.998e+00 3.000e+00
 3.003e+00 3.004e+00 3.010e+00 3.021e+00 3.022e+00 3.023e+00 3.025e+00
 3.032e+00 3.035e+00 3.043e+00 3.045e+00 3.050e+00 3.052e+00 3.053e+00
 3.058e+00 3.060e+00 3.061e+00 3.065e+00 3.070e+00 3.071e+00 3.075e+00
 3.085e+00 3.090e+00 3.091e+00 3.095e+00 3.100e+00 3.109e+00 3.112e+00
 3.120e+00 3.122e+00 3.125e+00 3.128e+00 3.157e+00 3.160e+00 3.165e+00
 3.171e+00 3.175e+00 3.194e+00 3.197e+00 3.198e+00 3.210e+00 3.221e+00
 3.266e+00 3.295e+00 3.302e+00 3.320e+00 3.327e+00 3.343e+00 3.365e+00
 3.450e+00 3.465e+00 3.516e+00 3.552e+00 3.670e+00 3.672e+00 3.683e+00
 3.688e+00 3.759e+00 3.860e+00 3.987e+00 4.016e+00 4.035e+00 4.037e+00
 4.260e+00 2.715e+03 2.850e+03 3.110e+03]
Trunk Capacity [   45.    85.    96.   104.   107.   110.   113.   115.   125.   128.
   131.   132.   133.   135.   139.   140.   144.   150.   152.   160.
   161.   165.   170.   173.   184.   185.   195.   196.   197.   198.
   206.   207.   211.   213.   220.   224.   225.   230.   235.   236.
   240.   241.   243.   244.   245.   249.   252.   254.   255.   258.
   259.   260.   261.   265.   266.   270.   271.   275.   276.   277.
   278.   280.   283.   284.   285.   286.   288.   290.   291.   292.
   294.   295.   300.   305.   306.   310.   314.   315.   320.   324.
   330.   331.   332.   334.   335.   340.   341.   342.   343.   344.
   346.   348.   349.   350.   351.   355.   356.   357.   358.   360.
   362.   368.   370.   372.   374.   375.   378.   380.   381.   382.
   384.   385.   388.   389.   390.   395.   396.   397.   398.   400.
   402.   405.   406.   407.   408.   414.   420.   421.   423.   424.
   425.   427.   430.   432.   433.   435.   436.   443.   445.   446.
   447.   448.   450.   451.   453.   455.   456.   458.   459.   460.
   461.   462.   465.   467.   468.   470.   473.   476.   478.   480.
   481.   482.   484.   485.   486.   487.   490.   492.   493.   495.
   500.   502.   503.   504.   505.   506.   510.   513.   515.   517.
   520.   521.   525.   530.   532.   535.   538.   540.   543.   544.
   545.   548.   550.   553.   562.   563.   568.   569.   572.   574.
   577.   580.   583.   590.   592.   595.   600.   605.   608.   610.
   615.   625.   630.   639.   645.   648.   650.   651.   668.   670.
   675.   679.   680.   690.   691.   700.   702.   714.   736.   742.
   745.   750.   770.   780.   782.   784.   790.   800.   830.   838.
   841.   844.   846.   849.   875.   890.   894.   895.   898.   900.
   915.   952.   960.   965.   971.   974.   981.   994.  1028.  1050.
  1059.  1075.  1081.  1085.  1087.  1093.  1100.  1107.  1111.  1113.
  1150.  1180.  1192.  1223.  1239.  1240.  1372.  1438.  1461.  1500.
  1530.  1540.  1568.  1690.  1727.  1801.  1833.  1842.  1855.  1868.
  2038.  2138.  2302.  2444.  2800.  3400.  3700.  4410.  6000.  6200.
  6986.  9800. 11450. 11500. 13800. 17000.]
name ['Abarth 124 Spider 2021 1.4T (170 HP)'
 'Abarth 595 2021 1.4T Competizione (Convertible)'
 'Abarth 595 2021 1.4T Competizione (Hard-Top)' ...
 'Volvo XC90 2021 2.0T T6 AWD R Design' 'ZNA Rich 2021 2.4L DC (4x2)'
 'ZNA Rich 2021 2.4L DC (4x4)']
price [2.899e+03 2.950e+03 3.000e+03 ... 9.600e+06 9.975e+06 1.078e+07]
currency [0 1 2 3 4 5]
Country [0 1 2 3 4 5]
brand ['Abarth' 'Acura' 'Alfa' 'Aston' 'Audi' 'BAIC' 'BMW' 'BYD' 'Bentley'
 'Borgward' 'Bugatti' 'Cadillac' 'Changan' 'Chery' 'Chevrolet' 'Chrysler'
 'Citroen' 'Dodge' 'FAW' 'Ferrari' 'Fiat' 'Ford' 'GAC' 'GMC' 'Geely'
 'Genesis' 'Haval' 'Honda' 'Hyundai' 'Infiniti' 'Isuzu' 'JAC' 'Jaguar'
 'Jeep' 'Kia' 'Lamborghini' 'Land' 'Lexus' 'Lincoln' 'Lotus' 'MG'
 'Mahindra' 'Maserati' 'Maxus' 'Mazda' 'McLaren' 'Mercedes-Benz' 'Mini'
 'Mitsubishi' 'Nissan' 'Opel' 'Peugeot' 'Porsche' 'Proton' 'RAM' 'Renault'
 'Rolls' 'Seat' 'Skoda' 'SsangYong' 'Subaru' 'Suzuki' 'Toyota'
 'Volkswagen' 'Volvo' 'ZNA']
In [ ]:
categorical = ['Engine Capacity', 'Cylinders', 'Drive Type','Fuel Type', 'Transmission', 'Seating Capacity', 'currency', 'Country', 'brand']
for col in categorical:
  c = pd.Categorical(df[col])
  if col != 'brand':
    c = c.rename_categories([f'{col}{i}' for i in np.unique(df[col])])
  df[col] = c
In [ ]:
df.head()
Out[ ]:
Engine Capacity Cylinders Drive Type Fuel Tank Capacity Fuel Economy Fuel Type Horsepower Torque Transmission Top Speed ... Length Width Height Wheelbase Trunk Capacity name price currency Country brand
0 Engine Capacity1.2 Cylinders3 Drive Type0 42.0 4.9 Fuel Type0 76 100.0 Transmission0 170 ... 4.245 1.670 1.515 2.550 450.0 Mitsubishi Attrage 2021 1.2 GLX (Base) 34099.0 currency0 Country0 Mitsubishi
1 Engine Capacity1.2 Cylinders3 Drive Type0 42.0 4.9 Fuel Type0 76 100.0 Transmission0 170 ... 4.245 1.670 1.515 2.550 450.0 Mitsubishi Attrage 2021 1.2 GLX (Base) 34099.0 currency0 Country0 Mitsubishi
2 Engine Capacity1.4 Cylinders4 Drive Type0 45.0 6.3 Fuel Type0 75 118.0 Transmission1 156 ... 3.864 1.716 1.721 2.513 2800.0 Fiat Fiorino 2021 1.4L Standard 41250.0 currency0 Country0 Fiat
3 Engine Capacity1.6 Cylinders4 Drive Type0 50.0 6.4 Fuel Type0 102 145.0 Transmission0 180 ... 4.354 1.994 1.529 2.635 510.0 Renault Symbol 2021 1.6L PE 44930.0 currency0 Country0 Renault
4 Engine Capacity1.5 Cylinders4 Drive Type0 48.0 5.8 Fuel Type0 112 150.0 Transmission0 170 ... 4.314 1.809 1.624 2.585 448.0 MG ZS 2021 1.5L STD 57787.0 currency0 Country0 MG

5 rows × 22 columns

In [ ]:
y = df.loc[:,'price']
X_A = df.loc[:,categorical]
datasets['A'] = train_test_split(X_A, y, test_size=0.25, random_state=0)
In [ ]:
X_B = df.loc[:,list(set(df.columns) - set(categorical) - {'price', 'name'})]
datasets['B'] = train_test_split(X_B, y, test_size=0.25, random_state=0)
In [ ]:
X_C = pd.get_dummies(df[categorical[0]])
for i in range(1, len(categorical)):
    c = pd.get_dummies(df[categorical[i]])
    X_C = pd.concat([X_C, c], axis=1)
datasets['C'] = train_test_split(X_C, y, test_size=0.25, random_state=0)

Итак, кажется, что у нас всё готово для того, чтобы начать искать ответы на волнующие нас вопросы. Начнем со столь любимой нами библиотеки, а именно...

Градиентный бустинг со sklearn¶

Естественно, в sklearn имеется реализация градиентного бустинга, которая хранится в sklearn.ensemble.GradientBoostingRegressor. Преимущественно данным классом пользуются в учебных заданиях, а в реальных задачах предпочтение отдаётся другим библиотекам. Давайте попробуем понять, заслуженно ли градиентный бустинг в sklearn не пользуется популярностью.

FYI: в sklearn имеется также реализация GradientBoostingClassifier для задач классификации, но пользоваться им мы сегодня не будем.

GradientBoostingRegressor из коробки не умеет работать с категориальными признаками. Мы к этому уже подготовились, закодировав наши признаки.

**Задание 2 (кросс-проверка, 2 балла)**¶

Данные: датасет со стоимостью подержанных автомобилей
Метрика: MAE
Цели: В данном задании следует выполнить следующие пункты:

  1. Обучить sklearn.ensemble.GradientBoostingRegressor на датасетах B и C(получится два разных регрессора), используя параметры n_estimators=1000, max_depth=5, learning_rate=0.1 (наши test_parameters). Замерить время обучения.
  2. Посчитать MAE для предсказаний на соответствующих тренировочном и тестовом множествах (можно воспользоваться sklearn.metrics.mean_absolute_error). Замерить время предсказания.
  3. Вывести в таблице DataFrame результаты о времени обучения, времени предсказания, MAE на тренировочном и тестовом множествах. **Внимание!** Для каждого из последующих заданий создавайте новые переменные для таблиц DataFrame - в задании 6 необходимо будет объединить все полученные результаты
  4. Сделайте выводы. Оцените полезность категориальных переменных. Оцените время, затраченное на обучение. Попробуйте дать оценку получившемуся MAE: оно большое или маленькое?
In [ ]:
df_skl = pd.DataFrame(columns=['Dataset', 'Training time', 'Prediction time', 'Train MAE', 'Test MAE'])

# your cool code here
In [ ]:
for dataset in ['B', 'C']:
  skl_boosting = GradientBoostingRegressor(n_estimators=test_parameters['n_estimators'],
                                           max_depth=test_parameters['max_depth'],
                                           learning_rate=test_parameters['learning_rate'])
  new_row = {}
  new_row['Dataset'] = dataset

  start = time.time()
  skl_boosting.fit(datasets[dataset][0], datasets[dataset][2])
  new_row['Training time'] = time.time() - start

  start_pred_train = time.time()
  new_row['Train MAE'] = mean_absolute_error(skl_boosting.predict(datasets[dataset][0]), datasets[dataset][2])
  pred_train_time = time.time() - start_pred_train

  start_pred_test = time.time()
  new_row['Test MAE'] = mean_absolute_error(skl_boosting.predict(datasets[dataset][1]), datasets[dataset][3])
  pred_test_time = time.time() - start_pred_test

  new_row['Prediction time'] = pred_test_time + pred_train_time

  df_skl = df_skl.append(new_row, ignore_index=True)
<ipython-input-17-a1834f3ed0c8>:22: FutureWarning: The frame.append method is deprecated and will be removed from pandas in a future version. Use pandas.concat instead.
  df_skl = df_skl.append(new_row, ignore_index=True)
<ipython-input-17-a1834f3ed0c8>:22: FutureWarning: The frame.append method is deprecated and will be removed from pandas in a future version. Use pandas.concat instead.
  df_skl = df_skl.append(new_row, ignore_index=True)
In [ ]:
df_skl
Out[ ]:
Dataset Training time Prediction time Train MAE Test MAE
0 B 9.958316 0.134093 92025.145047 123404.872551
1 C 25.757680 0.334569 12849.468358 24476.732434

Выводы: MAE c OHE значительно меньше, значит такое представление датасета оптимальнее. Время затраченное на обучение больше на датасете C, что логично, так как имеем больше признаков для которых нужно изучить веса.

И так, sklearn предлагает нам привычный и простой способ тренировки моделей. Однако для градиентного бустинга существует множество эвристик и трюков, помогающих улучшить результаты. И одна из библиотек, реализующая улучшенную версию бустинга, называется XGBoost.


Градиентный бустинг с XGBoost¶

XGBoost стала достаточно популярной библиотекой, которая позволяет добиться хороших результатов без особых усилий (во всяком случае, так гласят легенды). И у нас для вас две новости: хорошая и плохая.

Хорошая — XGBoost, хоть и является сторонней библиотекой, сохраняет интерфейс sklearn.

Плохая — она тоже не умеет из коробки работать с категориальными признаками.

Ну что же, давайте пощупаем это безобразие. На этот раз нас интересует класс XGBRegressor.

Daily Fact: на самом деле в XGBoost есть экспериментальная поддержка категориальных переменных, которая еще не добавлена в стабильную версию, поэтому ею мы пользоваться не будем.

**Задание 3 (кросс-проверка, 2 балла)**¶

Данные: датасет со стоимостью подержанных автомобилей
Метрика: MAE
Цели: В данном задании следует выполнить следующие пункты:

  1. Обучить xgboost.XGBRegressor на датасетах B и C, используя параметры n_estimators=1000, max_depth=5, learning_rate=0.1 (наши test_parameters). Замерить время обучения.
  2. Посчитать MAE для полученных предсказаний на соответствующих тренировочном и тестовом множествах (можно воспользоваться sklearn.metrics.mean_absolute_error). Замерить время предсказания
  3. Вывести в таблице DataFrame результаты о времени обучения, времени предсказания, MAE на тренировочном и тестовом множествах.
  4. Сделайте выводы. Оцените время, затраченное на обучение, сравните с sklearn.
In [ ]:
df_xgb = pd.DataFrame(columns=['Dataset', 'Training time', 'Prediction time', 'Train MAE', 'Test MAE'])

# your perfect code here
In [ ]:
for dataset  in ['B', 'C']:
  xgb_boosting = XGBRegressor(n_estimators=test_parameters['n_estimators'],
                              max_depth=test_parameters['max_depth'],
                              learning_rate=test_parameters['learning_rate'])
  new_row = {}
  new_row['Dataset'] = dataset

  start_time = time.time()
  xgb_boosting.fit(datasets[dataset][0], datasets[dataset][2])
  new_row['Training time'] = time.time() - start_time

  start_train = time.time()
  new_row['Train MAE'] = mean_absolute_error(xgb_boosting.predict(datasets[dataset][0]), datasets[dataset][2])
  pred_train_time = time.time() - start_train

  start_test = time.time()
  new_row['Test MAE'] = mean_absolute_error(xgb_boosting.predict(datasets[dataset][1]), datasets[dataset][3])
  pred_test_time = time.time() - start_test

  new_row['Prediction time'] = pred_train_time + pred_test_time

  df_xgb = df_xgb.append(new_row, ignore_index=True)
In [ ]:
df_xgb
Out[ ]:
Dataset Training time Prediction time Train MAE Test MAE
0 B 10.209576 0.073732 92397.086231 123321.632133
1 C 19.287345 0.123291 14828.175914 25662.812282

Выводы: XGBoost показал сравнимые с sklearn результаты. Так же как и в sklearn на датасете C с OHE закодированными категориальными признаками качество лучше. Время обучения значительно больше для датасета С.


Таким вот несложным образом нам удалось воспользоваться еще одной библиотекой. Давайте перейдем к третьей библиотеке, которую мы сегодня изучим, и называется она lightgbm.

Градиентный бустинг в lightgbm¶

Про Lightgbm легенды гласят, что она очень быстрая и легкая: что самый большой датасет она без проблем переварит за относительно небольшое время. А еще её разрабатывали не хухры кто, а сами мелкомягкие, так что попробовать её определённо стоит. На этот раз у нас вновь две новости, две хороших и две плохих.

Первая хорошая — lightgbm тоже похож на sklearn. Вторая хорошая — lightgbm умеет из коробки работать с категориальными признаками!

Плохая — делает она это немного нетривиально (не зря я просил вас запомнить категориальные переменные!). Вторая плохая — да, нам придётся этим пользоваться для выполнения задания.

**Внимание!** LightGBM может писать сотню радостных сообщений о том, что он увидел ваши categorical_feature и использует их. При желании можете заглушать эти оповещения, ибо в случае перебора параметров их становится слишком много. (заклинание для заглушения: warnings.filterwarnings("ignore"))

**Задание 4 (кросс-проверка, 3 балла)**¶

Данные: датасет со стоимостью подержанных автомобилей
Метрика: MAE
Цели: В данном задании следует выполнить следующие пункты:

  1. В случае датасета, сохраненного в numpy, lightgbm требует, чтобы категории были закодированы целыми числами от 0 до числа признаков(e.g. ['a', 'b', 'a'] -> [0, 1, 0]). Сделайте это для датасета A. Если вы используете pandas, то для датасета A достаточно установить соответствующие столбцы типа "категория", тогда categorical_feature='auto' сам всё подхватит.
  2. Обучить lightgbm.LGBMRegressor на датасетах A, B и C, используя параметры n_estimators=1000, max_depth=5, learning_rate=0.1. В случае датасета A, передайте в функцию fit индексы/имена категориальных признаков. Замерить время обучения.
  3. Посчитать MAE для полученных предсказаний на соответствующих тренировочном и тестовом множествах (можно воспользоваться sklearn.metrics.mean_absolute_error). Сделайте выводы о полезности использования категориальных переменных и времени обучения.
  4. Вывести результаты и время в таблице DataFrame.
In [ ]:
import warnings
warnings.filterwarnings("ignore")

df_lightgbm = pd.DataFrame(columns=['Dataset', 'Training time', 'Prediction time', 'Train MAE', 'Test MAE'])

# your sweet code here
In [ ]:
for dataset in ['A', 'B', 'C']:
  lgbm_boosting = LGBMRegressor(n_estimators=test_parameters['n_estimators'],
                                max_depth=test_parameters['max_depth'],
                                learning_rate=test_parameters['learning_rate'])
  new_row = {}
  new_row['Dataset'] = dataset
  start = time.time()
  lgbm_boosting.fit(datasets[dataset][0], datasets[dataset][2])
  new_row['Training time'] = time.time() - start

  start_train = time.time()
  new_row['Train MAE'] = mean_absolute_error(lgbm_boosting.predict(datasets[dataset][0]), datasets[dataset][2])
  pred_train_time = time.time() - start_train

  start_test = time.time()
  new_row['Test MAE'] = mean_absolute_error(lgbm_boosting.predict(datasets[dataset][1]), datasets[dataset][3])
  pred_test_time = time.time() - start_test

  new_row['Prediction time'] = pred_test_time + pred_train_time
  df_lightgbm = df_lightgbm.append(new_row, ignore_index=True)
In [ ]:
df_lightgbm
Out[ ]:
Dataset Training time Prediction time Train MAE Test MAE
0 A 1.057474 0.521982 22126.616779 35649.258538
1 B 0.907911 0.332465 98785.510109 122755.230317
2 C 0.877153 0.257977 41683.965402 50429.166140

Выводы: MAE для датасета А оказался самым низким, как на train так и на test, получатеся, что использование категориальных признаков дает хороший результат. Время обучения для С (где признаки уже были закодированы) оказалось самым маленьким, однако MAE выше, чем на датасете A.


Как вы видите, иногда можно не возиться с OHE, а позволить библиотекам самим это сделать (хотя иногда при этом приходится повозиться с самими данными, чтобы библиотека их съела).

Итак, мы с вами почти стали мастерами градиентного бустинга. Переходим к последней звезде нашего хит-парада.

Градиентный бустинг в catboost¶

Пролог: Why does catboost need random seed? It grows random trees!

Библиотека, созданная в тёмных подвалах Яндекса. По легендам эта библиотека умеет работать с категориальными данными, быстрая, эффективная, легко настраивается, из коробки понимает текстовые признаки в задачах классификации и спасла Брюса Уиллиса. Давайте проверим. В качестве регрессора нас интересует catboost.CatBoostRegressor.

**Внимание!** Эта библиотека еще более болтлива, чем lightgbm, но это (почти) полностью лечится с помощью verbose. Однако ноутбуки всё равно неприлично разрастаются в размерах, поэтому просим вас сделать следующее: обучать catboost в первой ячейке и очистить её вывод перед сдачей. Все необходимые выводы стоит делать во второй ячейке. Также можно воспользоваться clear_output()

А еще эта библиотека может неожиданно создать вам парочку новых папок...

**Задание 5 (кросс-проверка, 3 балла)**¶

Данные: датасет со стоимостью подержанных автомобилей
Метрика: MAE
Цели: В данном задании следует выполнить следующие пункты:

  1. Обучить catboost.CatBoostRegressor на датасетах A, B и C, используя параметры используя параметры n_estimators=1000, max_depth=5, learning_rate=0.1, verbose=False.
  2. В случае датасета A, передайте на вход методу fit/конструктору параметр cat_features, содержащий имена/индексы категориальных переменных. В данном случае переводить категории в целые числа, как мы делали для lightgbm, не нужно. Замерьте время обучения.
  3. Посчитать MAE для полученных предсказаний на соответствующих тренировочном и тестовом множествах (можно воспользоваться sklearn.metrics.mean_absolute_error).
  4. Сделайте выводы и полезности использования категориальных переменных и времени обучения.
  5. Вывести результаты и время в таблице DataFrame.
In [ ]:
from IPython.display import clear_output

df_catboost = pd.DataFrame(columns=['Dataset', 'Training time', 'Prediction time', 'Train MAE', 'Test MAE'])

# your cute code here
for dataset in ['A','B','C']:
  cat_boosting = CatBoostRegressor(n_estimators=test_parameters['n_estimators'],
                                  max_depth=test_parameters['max_depth'],
                                  learning_rate=test_parameters['learning_rate'],
                                  verbose=False)

  new_row = {}
  new_row['Dataset'] = dataset

  start_time = time.time()
  if dataset == 'A':
    cat_boosting.fit(datasets[dataset][0], datasets[dataset][2], cat_features=categorical, verbose=False)
  else:
    cat_boosting.fit(datasets[dataset][0], datasets[dataset][2], verbose=False)
  new_row['Training time'] = time.time() - start_time

  start_train = time.time()
  new_row['Train MAE'] = mean_absolute_error(cat_boosting.predict(datasets[dataset][0]), datasets[dataset][2])
  pred_train = time.time() - start_train

  start_test = time.time()
  new_row['Test MAE'] = mean_absolute_error(cat_boosting.predict(datasets[dataset][1]), datasets[dataset][3])
  pred_test = time.time() - start_test

  new_row['Prediction time'] = pred_test + pred_train
  df_catboost = df_catboost.append(new_row, ignore_index=True)
clear_output() # может быть полезно если catboost будет слишком болтливым и неумолкаемым (чтобы не сдавать ноутбуки с кучей ненужного кода)
In [ ]:
df_catboost
Out[ ]:
Dataset Training time Prediction time Train MAE Test MAE
0 A 7.758803 0.042744 24481.306853 25355.243965
1 B 2.982864 0.010152 99543.603852 121881.665671
2 C 1.253168 0.023696 19561.799709 26330.437096

Выводы: Качество на датасетах с категориальными признаками лучше, чем на датасете без них. В свою очередь качество на датасете с OHE чуть лучше, чем без него.


И так, мы наконец познакомились со всеми библиотеками градиентного бустинга.

Обобщение результатов¶

На текущем этапе у вас должно быть несколько датафреймов результатами по каждой библиотеке. Мы, конечно, сделали некоторые выводы, но пришло время собрать это в красивый отчет.

Задание 6 (кросс-проверка, 2 балла):¶

Данные: датасет с ценами подержанных автомобилей
Цели: В данном задании следует выполнить следующие пункты:

  1. При помощи одного или нескольких графиков показать результаты различных библиотек: времени работы и качество результатов. Можете воспользоваться любым типом графиков: гистограммы, scatter и т.д. По этим графикам должно быть понятно какая библиотека и насколько быстрее, насколько различается их качество.
  2. По графикам сравните библиотеки, производительность и качество работы. Опишите ваши выводы ниже.
In [ ]:
# Your great pictures and conclusions below!

import seaborn as sns
import plotly.express as px
import plotly.io as pio
from plotly.subplots import make_subplots
import plotly.graph_objects as go
pio.renderers.default='notebook'
In [92]:
fig, axes = plt.subplots(3, 1)

sns.set(font_scale=7)
fig.suptitle('Результаты GradientBoostingRegressor')
plt.subplot(3, 1, 1)
sns.barplot(x='Dataset',
            y='Train MAE',
            data=df_skl).set(title='Зависимость Train MAE от параметров и датасета')
plt.subplot(3, 1, 2)
sns.barplot(x='Dataset',
            y='Test MAE',
            data=df_skl).set(title='Зависимость Test MAE от параметров и датасета')
plt.subplot(3, 1, 3)
sns.barplot(x='Dataset',
            y='Training time',
            data=df_skl).set(title='Зависимость времени обучения от параметров и датасета')

fig.set_figwidth(100)
fig.set_figheight(100)
In [ ]:
fig, axes = plt.subplots(3, 1)

sns.set(font_scale=7)
fig.suptitle('Результаты XGBRegressor')
plt.subplot(3, 1, 1)
sns.barplot(x='Dataset',
            y='Train MAE',
            data=df_xgb).set(title='Зависимость Train MAE от параметров и датасета')
plt.subplot(3, 1, 2)
sns.barplot(x='Dataset',
            y='Test MAE',
            data=df_xgb).set(title='Зависимость Test MAE от параметров и датасета')
plt.subplot(3, 1, 3)
sns.barplot(x='Dataset',
            y='Training time',
            data=df_xgb).set(title='Зависимость времени обучения от параметров и датасета')

fig.set_figwidth(100)
fig.set_figheight(100)
In [ ]:
fig, axes = plt.subplots(3, 1)

sns.set(font_scale=7)
fig.suptitle('Результаты LGBMRegressor')
plt.subplot(3, 1, 1)
sns.barplot(x='Dataset',
            y='Train MAE',
            data=df_lightgbm).set(title='Зависимость Train MAE от параметров и датасета')
plt.subplot(3, 1, 2)
sns.barplot(x='Dataset',
            y='Test MAE',
            data=df_lightgbm).set(title='Зависимость Test MAE от параметров и датасета')
plt.subplot(3, 1, 3)
sns.barplot(x='Dataset',
            y='Training time',
            data=df_lightgbm).set(title='Зависимость времени обучения от параметров и датасета')

fig.set_figwidth(100)
fig.set_figheight(100)
In [ ]:
fig, axes = plt.subplots(3, 1)

sns.set(font_scale=7)
fig.suptitle('Результаты CatBoostRegressor')
plt.subplot(3, 1, 1)
sns.barplot(x='Dataset',
            y='Train MAE',
            data=df_catboost).set(title='Зависимость Train MAE от параметров и датасета')
plt.subplot(3, 1, 2)
sns.barplot(x='Dataset',
            y='Test MAE',
            data=df_catboost).set(title='Зависимость Test MAE от параметров и датасета')
plt.subplot(3, 1, 3)
sns.barplot(x='Dataset',
            y='Training time',
            data=df_catboost).set(title='Зависимость времени обучения от параметров и датасета')

fig.set_figwidth(100)
fig.set_figheight(100)

Выводы: Исходя из графиков, можно сделать вывод что лучшие результаты у библиотек lightgbm и catboost. В целом результаты лучше всего на датасете C, то есть на датасете с OHE кодированием. По времени обучения так же выигрывают эти библиотеки.


Оптимизация параметров¶

И так, мы с вами научились пользоваться библиотеками для градиентного бустинга. Пришло время заняться самой интересной (нет) частью исследований, а именно подбором параметров!

Выберите любые две библиотеки из тех, с которыми мы работали в этом ноутбуке, и осуществите для них перебор параметров по сетке.

Обратите внимание, что:

  1. Для всех библиотек вы можете воспользоваться классом GridSearchCV, реализованном в sklearn, осуществляющим кросс-валидацию всех параметров и поиск модели с лучшим качеством. Этот класс позволяет установить количество разбиений датасета, что достаточно сильно влияет на время работы. Также вы можете воспользоваться n_jobs = -1 для распараллеливания процесса перебора. **Внимание!** Если вы устанавливаете n_jobs для GridSearchCV, то не надо использовать этот параметр для обучаемых регрессоров! Результат может быть плачевным в плане времени...
  2. В CatBoost существует своя реализация перебора параметров, которым также можно воспользоваться (речь о grid_search).
  3. Для подбора правильной сетки параметров советуем обратиться к краткому руководству в начале ноутбука.

**Задание 7.1 (кросс-проверка, 5 баллов)**¶

Данные: датасет со стоимостью подержанных автомобилей
Метрика: MAE
Цели: В данном задании следует выполнить следующие пункты:

  1. Взять две любые библиотеки градиентного бустинга (можете взять самые быстрые)
  2. Составить сетку перебора параметров, включающую не менее трех параметров из n_estimators, max_depth, subsample и learning_rate.
  3. Осуществите перебор параметров по вашей сетке при помощи GridSearchCV на датасетах B и C. Замерьте время перебора. Посчитайте качество моделиобученной с оптимальными (с позиции кросс-валидации) параметрами на тренировочном и тестовом множествах.
  4. Сделайте выводы о полезности перебора параметров.

**Внимание!**

По какой-то причине, которую нам не удалось выяснить, иногда catboost в google colab работает очень медленно при переборе параметров. Если в соответствующем задании время обучения catboost занимает не многим более 10 секунд, то в случае кросс-валидации оно возрастает до 5 минут (соответственно, 5 минут в каждом из узлов). Поэтому используйте catboost на свой страх и риск :)

In [ ]:
scorer = make_scorer(mean_absolute_error)
In [ ]:
df_optimized = pd.DataFrame(columns=['Library', 'Dataset', 'Training time', 'Train MAE', 'Test MAE'])

# your ideal code goes here
In [ ]:
parameters_lgbm_B = {'n_estimators': [1000, 2000, 3000],
                     'max_depth': np.arange(5, 9),
                     'learning_rate': np.logspace(-5, -1, 5),
                      'subsample': [0.25, 0.5, 1]}
In [ ]:
base_lgbm = LGBMRegressor()
lgbm_boosting_B = GridSearchCV(base_lgbm, parameters_lgbm_B, scoring=scorer, cv=3)
start_time_lgbm_B = time.time()
lgbm_boosting_B.fit(datasets['B'][0], datasets['B'][2])
end_time_lgbm_B = time.time() - start_time_lgbm_B
In [ ]:
res_lgbm_B = pd.DataFrame(pd.DataFrame(lgbm_boosting_B.cv_results_))
res_lgbm_B.sort_values(by='mean_test_score')
Out[ ]:
mean_fit_time std_fit_time mean_score_time std_score_time param_learning_rate param_max_depth param_n_estimators param_subsample params split0_test_score split1_test_score split2_test_score mean_test_score std_test_score rank_test_score
144 0.761246 0.012482 0.077602 0.007239 0.1 5 1000 0.25 {'learning_rate': 0.1, 'max_depth': 5, 'n_esti... 118003.183954 131756.723887 137506.652328 129088.853390 8182.683724 178
145 0.769980 0.015428 0.077151 0.003384 0.1 5 1000 0.5 {'learning_rate': 0.1, 'max_depth': 5, 'n_esti... 118003.183954 131756.723887 137506.652328 129088.853390 8182.683724 178
146 0.770613 0.027570 0.078900 0.004851 0.1 5 1000 1 {'learning_rate': 0.1, 'max_depth': 5, 'n_esti... 118003.183954 131756.723887 137506.652328 129088.853390 8182.683724 178
153 0.845558 0.029701 0.094413 0.003438 0.1 6 1000 0.25 {'learning_rate': 0.1, 'max_depth': 6, 'n_esti... 117864.028033 131773.766902 137971.885939 129203.226958 8407.823503 175
154 0.864301 0.036754 0.093848 0.007414 0.1 6 1000 0.5 {'learning_rate': 0.1, 'max_depth': 6, 'n_esti... 117864.028033 131773.766902 137971.885939 129203.226958 8407.823503 175
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
11 1.226817 0.214357 0.083694 0.006344 0.00001 6 1000 1 {'learning_rate': 1e-05, 'max_depth': 6, 'n_es... 150302.117868 144844.808748 168939.124508 154695.350374 10315.340740 4
10 1.205429 0.251694 0.081177 0.016664 0.00001 6 1000 0.5 {'learning_rate': 1e-05, 'max_depth': 6, 'n_es... 150302.117868 144844.808748 168939.124508 154695.350374 10315.340740 4
2 0.921031 0.059298 0.053021 0.007976 0.00001 5 1000 1 {'learning_rate': 1e-05, 'max_depth': 5, 'n_es... 150321.881410 144855.179125 168932.252684 154703.104406 10306.072773 1
1 1.148455 0.135496 0.066294 0.019883 0.00001 5 1000 0.5 {'learning_rate': 1e-05, 'max_depth': 5, 'n_es... 150321.881410 144855.179125 168932.252684 154703.104406 10306.072773 1
0 0.998591 0.102521 0.065956 0.022935 0.00001 5 1000 0.25 {'learning_rate': 1e-05, 'max_depth': 5, 'n_es... 150321.881410 144855.179125 168932.252684 154703.104406 10306.072773 1

180 rows × 15 columns

In [ ]:
print('Время, затраченное на перебор: ', end_time_lgbm_B)
Время, затраченное на перебор:  1179.5379176139832
In [ ]:
lgbm_boosting_best_B = LGBMRegressor(**lgbm_boosting_B.best_params_)
new_row = {}
new_row['Library'] = 'LightGBM'
new_row['Dataset'] = 'B'
start_time = time.time()
lgbm_boosting_best_B.fit(datasets['B'][0], datasets['B'][2])
new_row['Training time'] = time.time() - start_time
new_row['Train MAE'] = mean_absolute_error(lgbm_boosting_best_B.predict(datasets['B'][0]), datasets['B'][2])
new_row['Test MAE'] = mean_absolute_error(lgbm_boosting_best_B.predict(datasets['B'][1]), datasets['B'][3])
df_optimized = df_optimized.append(new_row, ignore_index=True)
In [ ]:
parameters_lgbm_C = {'n_estimators': [1000, 2000, 3000, 4000, 5000],
                     'max_depth': np.arange(5, 11),
                     'learning_rate': np.logspace(-3, -1, 3),
                     'subsample': [0.25, 0.5, 1]}
In [ ]:
base_lgbm = LGBMRegressor()
lgbm_boosting_C = GridSearchCV(base_lgbm, parameters_lgbm_C, scoring=scorer, cv=3)
start_time_lgbm_C = time.time()
lgbm_boosting_C.fit(datasets['C'][0], datasets['C'][2])
end_time_lgbm_C = time.time() - start_time_lgbm_C
In [ ]:
res_lgbm_C = pd.DataFrame(pd.DataFrame(lgbm_boosting_C.cv_results_))
res_lgbm_C.sort_values(by='mean_test_score')
Out[ ]:
mean_fit_time std_fit_time mean_score_time std_score_time param_learning_rate param_max_depth param_n_estimators param_subsample params split0_test_score split1_test_score split2_test_score mean_test_score std_test_score rank_test_score
269 4.166204 0.263304 0.979585 0.277776 0.1 10 5000 1 {'learning_rate': 0.1, 'max_depth': 10, 'n_est... 50004.022474 51573.964010 67081.490372 56219.825619 7707.053047 268
267 4.321155 0.449439 0.867989 0.070422 0.1 10 5000 0.25 {'learning_rate': 0.1, 'max_depth': 10, 'n_est... 50004.022474 51573.964010 67081.490372 56219.825619 7707.053047 268
268 4.371834 0.289602 0.799461 0.047661 0.1 10 5000 0.5 {'learning_rate': 0.1, 'max_depth': 10, 'n_est... 50004.022474 51573.964010 67081.490372 56219.825619 7707.053047 268
266 3.430143 0.453307 0.673221 0.046389 0.1 10 4000 1 {'learning_rate': 0.1, 'max_depth': 10, 'n_est... 50159.078569 51842.375286 67317.777219 56439.743691 7722.567882 265
265 3.444991 0.453917 0.708441 0.051104 0.1 10 4000 0.5 {'learning_rate': 0.1, 'max_depth': 10, 'n_est... 50159.078569 51842.375286 67317.777219 56439.743691 7722.567882 265
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
17 0.883209 0.065223 0.089453 0.015001 0.001 6 1000 1 {'learning_rate': 0.001, 'max_depth': 6, 'n_es... 97045.662542 92629.415608 108961.048560 99545.375570 6897.679930 4
15 0.848259 0.059004 0.089037 0.004534 0.001 6 1000 0.25 {'learning_rate': 0.001, 'max_depth': 6, 'n_es... 97045.662542 92629.415608 108961.048560 99545.375570 6897.679930 4
2 0.843743 0.013433 0.064669 0.004917 0.001 5 1000 1 {'learning_rate': 0.001, 'max_depth': 5, 'n_es... 101319.040657 98449.388214 110586.042079 103451.490316 5179.131068 1
1 0.843886 0.009219 0.059969 0.001689 0.001 5 1000 0.5 {'learning_rate': 0.001, 'max_depth': 5, 'n_es... 101319.040657 98449.388214 110586.042079 103451.490316 5179.131068 1
0 0.975516 0.097028 0.070480 0.015763 0.001 5 1000 0.25 {'learning_rate': 0.001, 'max_depth': 5, 'n_es... 101319.040657 98449.388214 110586.042079 103451.490316 5179.131068 1

270 rows × 15 columns

In [ ]:
print('Время, затраченное на перебор: ', end_time_lgbm_C)
Время, затраченное на перебор:  2313.668661594391
In [ ]:
lgbm_boosting_best_C = LGBMRegressor(**lgbm_boosting_C.best_params_)
new_row = {}
new_row['Library'] = 'LightGBM'
new_row['Dataset'] = 'C'
start_time = time.time()
lgbm_boosting_best_C.fit(datasets['C'][0], datasets['C'][2])
new_row['Training time'] = time.time() - start_time
new_row['Train MAE'] = mean_absolute_error(lgbm_boosting_best_C.predict(datasets['C'][0]), datasets['C'][2])
new_row['Test MAE'] = mean_absolute_error(lgbm_boosting_best_C.predict(datasets['C'][1]), datasets['C'][3])
df_optimized = df_optimized.append(new_row, ignore_index=True)
In [ ]:
parameters_cat_B = {'n_estimators': [1000, 2000, 3000],
                    'max_depth': np.arange(5, 9),
                    'learning_rate': np.logspace(-5, -1, 5),
                    'subsample': [0.25, 0.5, 1]}
In [ ]:
cat_boosting_B = CatBoostRegressor(verbose=False)
start_time_cat_B = time.time()
grid_search_result_B = cat_boosting_B.grid_search(parameters_cat_B,
                                       X=datasets['B'][0],
                                       y=datasets['B'][2],
                                       cv=3,
                                       verbose=False,
                                       plot=True)
end_time_cat_B = time.time() - start_time_cat_B
In [ ]:
print('Время, затраченное на перебор: ', end_time_cat_B)
Время, затраченное на перебор:  1626.5342011451721
In [ ]:
cat_boosting_best_B = CatBoostRegressor(n_estimators=1000,
                                        max_depth=8,
                                        learning_rate=0.1,
                                        verbose=False)
new_row = {}
new_row['Library'] = 'CatBoost'
start_time = time.time()
cat_boosting_best_B.fit(datasets['B'][0], datasets['B'][2])
new_row['Training time'] = time.time() - start_time
new_row['Dataset'] = 'B'
new_row['Train MAE'] = mean_absolute_error(cat_boosting_best_B.predict(datasets['B'][0]), datasets['B'][2])
new_row['Test MAE'] = mean_absolute_error(cat_boosting_best_B.predict(datasets['B'][1]), datasets['B'][3])
df_optimized = df_optimized.append(new_row, ignore_index=True)
In [ ]:
parameters_cat_C = {'n_estimators': [1000, 2000, 3000],
                    'max_depth': np.arange(5, 9),
                    'learning_rate': np.logspace(-5, -1, 5),
                    'subsample': [0.25, 0.5, 1]}
In [ ]:
cat_boosting_C = CatBoostRegressor(verbose=False)
start_time_cat_C = time.time()
grid_search_result_C = cat_boosting_C.grid_search(parameters_cat_C,
                                       X=datasets['C'][0],
                                       y=datasets['C'][2],
                                       cv=3,
                                       verbose=False,
                                       plot=True)
end_time_cat_C = time.time() - start_time_cat_C
In [ ]:
print('Время, затраченное на перебор: ', end_time_cat_C)
Время, затраченное на перебор:  825.986743927002
In [ ]:
cat_boosting_best_C = CatBoostRegressor(n_estimators=2000,
                                        max_depth=5,
                                        learning_rate=0.1,
                                        verbose=False)
new_row = {}
new_row['Library'] = 'CatBoost'
start_time = time.time()
cat_boosting_best_C.fit(datasets['C'][0], datasets['C'][2])
new_row['Training time'] = time.time() - start_time
new_row['Dataset'] = 'C'
new_row['Train MAE'] = mean_absolute_error(cat_boosting_best_C.predict(datasets['C'][0]), datasets['C'][2])
new_row['Test MAE'] = mean_absolute_error(cat_boosting_best_C.predict(datasets['C'][1]), datasets['C'][3])
df_optimized = df_optimized.append(new_row, ignore_index=True)
In [ ]:
df_optimized
Out[ ]:
Library Dataset Training time Train MAE Test MAE
0 LightGBM B 1.213783 154559.349840 147743.748683
1 LightGBM C 1.407351 100231.736770 93828.102015
2 CatBoost B 9.075782 94985.925688 122813.038634
3 CatBoost C 3.874970 15649.423625 24996.950803

Выводы: Выбор оптимальных параметров, ожидаемо, привел к улучшению качества. Время обучения также увеличилось, что в целом ожидаемо. Датасеты с категориальными признаками стабильно показывают лучшие результаты, можем сделать предположение о том, что такое представление данных оптимально.

**[Бонус] Задание 7.2 (кросс-проверка, 4 балла)**¶

Данные: датасет со стоимостью подержанных автомобилей
Метрика: MAE
Цели: В данном задании следует выполнить следующие пункты:

  1. Выполнить задание 7.1 с использованием всех библиотек (для каждой библиотеки можно использовать свою сетку перебора). Разрешается использовать маленькие сетки с небольшим числом узлов, но не менее 8 (под узлом понимается число пересечений в сетке, а не число параметров; итого, для каждого из 3 параметров достаточно перебрать по 2 значения).
  2. Вывести ниже результаты работы с нашими дефолтными параметрами, а также с оптимальными.
  3. Вы будете получать 1 балл за каждую библиотеку с использованием которой точность с вашими подобранными параметрами превзойдет качество с использованием дефолтных параметров на тренировочной и тестовой выборках. Таким образом, максимальный балл за задание равен числу библиотек, 4 балла.
In [ ]:
# your genious code here
In [ ]:
parameters_skl_B = {'n_estimators': [1000, 1500, 2000, 2500],
                    'max_depth': np.arange(5, 8),
                    'learning_rate': np.logspace(-5, -1, 5)}
In [ ]:
base_skl = GradientBoostingRegressor()
skl_boosting_B = GridSearchCV(base_skl, parameters_skl_B, scoring=scorer, cv=3, n_jobs=-1)
start_time_skl_B = time.time()
skl_boosting_B.fit(datasets['B'][0], datasets['B'][2])
end_time_skl_B = time.time() - start_time_skl_B
In [ ]:
res_skl_B = pd.DataFrame(skl_boosting_B.cv_results_)
res_skl_B.sort_values(by='mean_test_score')
Out[ ]:
mean_fit_time std_fit_time mean_score_time std_score_time param_learning_rate param_max_depth param_n_estimators params split0_test_score split1_test_score split2_test_score mean_test_score std_test_score rank_test_score
42 25.649752 0.081668 0.087956 0.006099 0.01 6 2000 {'learning_rate': 0.01, 'max_depth': 6, 'n_est... 118196.934490 132477.981323 136210.106440 128961.674084 7762.813209 60
41 18.710378 0.398582 0.063500 0.002541 0.01 6 1500 {'learning_rate': 0.01, 'max_depth': 6, 'n_est... 118478.894452 132419.363976 135992.083856 128963.447428 7555.813222 59
40 12.598869 0.106508 0.073264 0.003793 0.01 6 1000 {'learning_rate': 0.01, 'max_depth': 6, 'n_est... 119112.895052 132247.288542 135554.233777 128971.472457 7100.593075 58
43 31.699866 0.685608 0.102478 0.002047 0.01 6 2500 {'learning_rate': 0.01, 'max_depth': 6, 'n_est... 118211.324563 132685.453614 136307.180571 129067.986250 7817.909088 57
44 14.337742 0.072995 0.051656 0.000656 0.01 7 1000 {'learning_rate': 0.01, 'max_depth': 7, 'n_est... 118637.202388 132621.143816 136244.181956 129167.509387 7591.535877 56
45 22.957194 0.759211 0.075379 0.001754 0.01 7 1500 {'learning_rate': 0.01, 'max_depth': 7, 'n_est... 118374.675228 132695.765254 136682.429788 129250.956757 7861.021920 55
37 16.471929 0.451336 0.059344 0.007282 0.01 5 1500 {'learning_rate': 0.01, 'max_depth': 5, 'n_est... 118877.609632 131874.000967 137019.485993 129257.032197 7634.060240 54
38 22.100505 0.862303 0.074016 0.005443 0.01 5 2000 {'learning_rate': 0.01, 'max_depth': 5, 'n_est... 118572.937348 132175.272532 137030.634352 129259.614744 7812.274100 53
39 27.865662 0.872900 0.121587 0.034744 0.01 5 2500 {'learning_rate': 0.01, 'max_depth': 5, 'n_est... 118502.068758 132252.727724 137081.862008 129278.886163 7871.254856 52
36 10.742732 0.541388 0.038963 0.002602 0.01 5 1000 {'learning_rate': 0.01, 'max_depth': 5, 'n_est... 119788.805029 131895.911122 136337.307766 129340.674639 6993.337821 51
46 28.581270 0.233099 0.098425 0.000764 0.01 7 2000 {'learning_rate': 0.01, 'max_depth': 7, 'n_est... 118292.113120 132955.219873 136973.284353 129406.872449 8028.682612 50
47 36.099512 0.730674 0.120688 0.004628 0.01 7 2500 {'learning_rate': 0.01, 'max_depth': 7, 'n_est... 118603.398966 133222.748907 137292.856911 129706.334928 8024.871132 49
31 34.190403 2.048471 0.134521 0.034207 0.001 6 2500 {'learning_rate': 0.001, 'max_depth': 6, 'n_es... 122403.533301 132135.984094 135397.237658 129978.918351 5519.588614 48
48 11.004875 0.130644 0.035994 0.000775 0.1 5 1000 {'learning_rate': 0.1, 'max_depth': 5, 'n_esti... 118352.929449 133835.620005 138036.263473 130074.937642 8464.256551 47
49 15.885960 0.169437 0.050865 0.000798 0.1 5 1500 {'learning_rate': 0.1, 'max_depth': 5, 'n_esti... 118432.306790 134112.542366 137993.186903 130179.345353 8456.143201 46
54 25.264519 0.053757 0.105701 0.037356 0.1 6 2000 {'learning_rate': 0.1, 'max_depth': 6, 'n_esti... 119067.119691 134193.303736 137398.831448 130219.751625 7993.945679 45
52 13.084687 0.476201 0.041928 0.001571 0.1 6 1000 {'learning_rate': 0.1, 'max_depth': 6, 'n_esti... 119090.406966 133929.109159 137798.449714 130272.655280 8063.289531 44
27 27.067468 0.412084 0.103151 0.018166 0.001 5 2500 {'learning_rate': 0.001, 'max_depth': 5, 'n_es... 122591.830194 132017.910107 136313.493531 130307.744611 5730.881881 43
50 22.044992 0.109469 0.073684 0.008732 0.1 5 2000 {'learning_rate': 0.1, 'max_depth': 5, 'n_esti... 118508.176962 134320.243041 138118.223813 130315.547938 8491.826326 42
35 36.062432 0.390891 0.160576 0.016872 0.001 7 2500 {'learning_rate': 0.001, 'max_depth': 7, 'n_es... 121615.456730 132635.968954 136890.086601 130380.504095 6436.558124 41
55 31.535863 0.525487 0.114266 0.022397 0.1 6 2500 {'learning_rate': 0.1, 'max_depth': 6, 'n_esti... 119186.940422 134129.400018 137851.782664 130389.374368 8065.768319 40
56 14.270600 0.133333 0.049816 0.000998 0.1 7 1000 {'learning_rate': 0.1, 'max_depth': 7, 'n_esti... 119060.287183 134072.526362 138087.997647 130406.937064 8189.051636 39
53 18.690803 0.468466 0.077361 0.025606 0.1 6 1500 {'learning_rate': 0.1, 'max_depth': 6, 'n_esti... 119146.370881 134123.138200 138014.711476 130428.073519 8134.031245 38
51 27.495523 0.548821 0.093186 0.010606 0.1 5 2500 {'learning_rate': 0.1, 'max_depth': 5, 'n_esti... 118553.184381 134457.487562 138331.920413 130447.530786 8558.014363 37
59 34.041608 3.648647 0.105497 0.010717 0.1 7 2500 {'learning_rate': 0.1, 'max_depth': 7, 'n_esti... 119055.719446 134355.019196 137937.303596 130449.347413 8188.172733 36
57 21.568461 0.671420 0.069988 0.000460 0.1 7 1500 {'learning_rate': 0.1, 'max_depth': 7, 'n_esti... 119069.169098 134152.757073 138194.411834 130472.112669 8230.191770 35
58 29.904779 0.475092 0.132437 0.029573 0.1 7 2000 {'learning_rate': 0.1, 'max_depth': 7, 'n_esti... 118974.354780 134329.959045 138127.834794 130477.382873 8280.326343 34
30 37.560179 7.802103 0.202812 0.017094 0.001 6 2000 {'learning_rate': 0.001, 'max_depth': 6, 'n_es... 123158.717197 131740.806886 136535.769438 130478.431174 5533.629068 33
34 28.955602 0.577327 0.118968 0.009254 0.001 7 2000 {'learning_rate': 0.001, 'max_depth': 7, 'n_es... 122391.732201 131972.302759 137529.225214 130631.086725 6252.203293 32
26 22.424646 0.243954 0.114473 0.036782 0.001 5 2000 {'learning_rate': 0.001, 'max_depth': 5, 'n_es... 123439.130435 131701.125661 137375.965150 130838.740415 5722.273540 31
33 21.422348 0.470678 0.148409 0.044288 0.001 7 1500 {'learning_rate': 0.001, 'max_depth': 7, 'n_es... 123722.922176 131671.688075 139288.131721 131560.913991 6354.952935 30
29 18.664357 0.470565 0.072270 0.002545 0.001 6 1500 {'learning_rate': 0.001, 'max_depth': 6, 'n_es... 124343.135870 131316.929279 139196.861721 131618.975624 6067.768229 29
25 16.218775 0.619484 0.057378 0.001688 0.001 5 1500 {'learning_rate': 0.001, 'max_depth': 5, 'n_es... 125069.866208 131596.706623 140064.321518 132243.631450 6138.528939 28
32 14.700268 0.332165 0.058861 0.000328 0.001 7 1000 {'learning_rate': 0.001, 'max_depth': 7, 'n_es... 127076.141241 132528.175458 143517.523445 134373.946714 6837.880561 27
28 12.289685 0.070748 0.076780 0.016947 0.001 6 1000 {'learning_rate': 0.001, 'max_depth': 6, 'n_es... 127533.767368 132158.710727 143763.812535 134485.430210 6827.093534 26
24 10.664946 0.271659 0.056712 0.020538 0.001 5 1000 {'learning_rate': 0.001, 'max_depth': 5, 'n_es... 128551.018346 132320.313827 144192.773840 135021.368671 6665.228262 25
23 35.787276 0.388212 0.148492 0.001560 0.0001 7 2500 {'learning_rate': 0.0001, 'max_depth': 7, 'n_e... 141498.511797 139071.548762 159370.934057 146646.998205 9051.572425 24
15 27.692221 0.120397 0.100385 0.003919 0.0001 5 2500 {'learning_rate': 0.0001, 'max_depth': 5, 'n_e... 141667.859533 138902.965731 159485.684010 146685.503092 9121.207270 23
19 32.248604 0.822791 0.132311 0.013781 0.0001 6 2500 {'learning_rate': 0.0001, 'max_depth': 6, 'n_e... 141719.012768 138902.814183 159568.246317 146730.024423 9150.508171 22
22 28.586518 0.359434 0.123032 0.006919 0.0001 7 2000 {'learning_rate': 0.0001, 'max_depth': 7, 'n_e... 143123.990985 139872.866880 161095.344476 148030.734114 9332.933977 21
14 23.100293 0.486017 0.080309 0.002888 0.0001 5 2000 {'learning_rate': 0.0001, 'max_depth': 5, 'n_e... 143216.665092 139743.866097 161177.796126 148046.109105 9393.117560 20
18 25.641656 0.569695 0.172495 0.053426 0.0001 6 2000 {'learning_rate': 0.0001, 'max_depth': 6, 'n_e... 143253.953706 139691.079171 161280.995106 148075.342661 9450.413082 19
21 21.336238 0.751234 0.096385 0.013450 0.0001 7 1500 {'learning_rate': 0.0001, 'max_depth': 7, 'n_e... 144840.894510 140749.758332 162909.320194 149499.991012 9627.804549 18
13 17.035837 0.757522 0.068835 0.009360 0.0001 5 1500 {'learning_rate': 0.0001, 'max_depth': 5, 'n_e... 144881.429728 140651.420415 162985.539407 149506.129850 9686.557909 17
17 19.485369 0.304193 0.115959 0.030638 0.0001 6 1500 {'learning_rate': 0.0001, 'max_depth': 6, 'n_e... 144928.443464 140574.002397 163080.792611 149527.746157 9746.934232 16
20 14.470267 0.441786 0.084346 0.033718 0.0001 7 1000 {'learning_rate': 0.0001, 'max_depth': 7, 'n_e... 146668.447313 141726.706089 164856.241876 151083.798426 9945.362421 15
12 11.373478 0.146022 0.042907 0.001008 0.0001 5 1000 {'learning_rate': 0.0001, 'max_depth': 5, 'n_e... 146657.830667 141690.886182 164912.951781 151087.222877 9984.345052 14
16 12.866878 0.158849 0.048766 0.000415 0.0001 6 1000 {'learning_rate': 0.0001, 'max_depth': 6, 'n_e... 146713.256315 141589.228467 164981.925772 151094.803518 10040.021206 13
11 36.509606 0.689963 0.165839 0.037975 0.00001 7 2500 {'learning_rate': 1e-05, 'max_depth': 7, 'n_es... 149628.163673 144246.678968 168060.107047 153978.316563 10196.820153 12
7 33.204211 0.653788 0.114785 0.000766 0.00001 6 2500 {'learning_rate': 1e-05, 'max_depth': 6, 'n_es... 149639.846384 144209.266428 168116.296839 153988.469884 10232.934429 11
3 27.941154 0.315307 0.093095 0.002680 0.00001 5 2500 {'learning_rate': 1e-05, 'max_depth': 5, 'n_es... 149611.589715 144238.909705 168115.457605 153988.652342 10227.133610 10
10 29.428542 0.071271 0.112753 0.005287 0.00001 7 2000 {'learning_rate': 1e-05, 'max_depth': 7, 'n_es... 149846.040560 144444.390536 168315.438719 154201.956605 10220.477444 9
2 22.245277 0.683226 0.079593 0.004067 0.00001 5 2000 {'learning_rate': 1e-05, 'max_depth': 5, 'n_es... 149832.830238 144437.409650 168366.683241 154212.307710 10248.167343 8
6 26.312838 0.100475 0.091600 0.001526 0.00001 6 2000 {'learning_rate': 1e-05, 'max_depth': 6, 'n_es... 149857.178241 144413.190032 168368.397200 154212.921824 10253.206466 7
9 22.502528 0.312983 0.085091 0.003437 0.00001 7 1500 {'learning_rate': 1e-05, 'max_depth': 7, 'n_es... 150065.281644 144644.196911 168578.525596 154429.334717 10246.844777 6
1 17.675742 1.114606 0.057741 0.002436 0.00001 5 1500 {'learning_rate': 1e-05, 'max_depth': 5, 'n_es... 150055.179738 144636.578633 168619.170777 154436.976383 10269.413741 5
5 19.818382 0.541274 0.074901 0.007078 0.00001 6 1500 {'learning_rate': 1e-05, 'max_depth': 6, 'n_es... 150073.748998 144618.951193 168622.185070 154438.295087 10273.777496 4
8 14.725633 0.193809 0.058829 0.000069 0.00001 7 1000 {'learning_rate': 1e-05, 'max_depth': 7, 'n_es... 150285.622186 144844.642810 168846.046566 154658.770521 10274.893846 3
0 10.833803 0.579348 0.041380 0.006321 0.00001 5 1000 {'learning_rate': 1e-05, 'max_depth': 5, 'n_es... 150279.047289 144838.354918 168873.548997 154663.650401 10290.487418 2
4 13.004069 0.134095 0.046328 0.000361 0.00001 6 1000 {'learning_rate': 1e-05, 'max_depth': 6, 'n_es... 150291.578805 144826.965526 168876.051213 154664.865181 10293.488424 1
In [ ]:
print('Время, затраченное на перебор: ', end_time_skl_B)
Время, затраченное на перебор:  2065.227844953537
In [ ]:
skl_boosting_best_B = GradientBoostingRegressor(**skl_boosting_B.best_params_)
new_row = {}
new_row['Library'] = 'SkLearn'
start_time = time.time()
skl_boosting_best_B.fit(datasets['B'][0], datasets['B'][2])
new_row['Training time'] = time.time() - start_time
new_row['Dataset'] = 'B'
new_row['Train MAE'] = mean_absolute_error(skl_boosting_best_B.predict(datasets['B'][0]), datasets['B'][2])
new_row['Test MAe'] = mean_absolute_error(skl_boosting_best_B.predict(datasets['B'][1]), datasets['B'][3])
df_optimized = df_optimized.append(new_row, ignore_index=True)
In [ ]:
parameters_skl_C = {'n_estimators': [2000, 3000, 4000, 4500],
                    'max_depth': np.arange(5, 9),
                    'learning_rate': np.logspace(-3, -1, 3)}
In [ ]:
base_skl = GradientBoostingRegressor()
skl_boosting_C = GridSearchCV(base_skl, parameters_skl_C, scoring=scorer, cv=3, n_jobs=-1)
start_time_skl_C = time.time()
skl_boosting_C.fit(datasets['C'][0], datasets['C'][2])
end_time_skl_C = time.time() - start_time_skl_C
In [ ]:
res_skl_C = pd.DataFrame(skl_boosting_C.cv_results_)
res_skl_C.sort_values(by='mean_test_score')
Out[ ]:
mean_fit_time std_fit_time mean_score_time std_score_time param_learning_rate param_max_depth param_n_estimators params split0_test_score split1_test_score split2_test_score mean_test_score std_test_score rank_test_score
42 76.403395 0.318961 0.158616 0.000641 0.1 7 4000 {'learning_rate': 0.1, 'max_depth': 7, 'n_esti... 27104.405047 32852.191496 34719.112143 31558.569562 3240.476747 48
31 98.044834 0.617430 0.224019 0.051909 0.01 8 4500 {'learning_rate': 0.01, 'max_depth': 8, 'n_est... 26646.998565 32077.678139 36331.615345 31685.430683 3963.444974 47
44 43.857805 0.231540 0.094780 0.002590 0.1 8 2000 {'learning_rate': 0.1, 'max_depth': 8, 'n_esti... 27254.509908 32837.941482 35491.530905 31861.327432 3432.924893 46
45 66.098390 0.956756 0.140711 0.003804 0.1 8 3000 {'learning_rate': 0.1, 'max_depth': 8, 'n_esti... 27084.034729 33126.957728 35527.593450 31912.861969 3552.364691 45
30 87.800088 0.419297 0.170963 0.002896 0.01 8 4000 {'learning_rate': 0.01, 'max_depth': 8, 'n_est... 26594.164024 32226.232494 36932.869518 31917.755346 4226.391403 44
41 57.045996 0.529449 0.155279 0.037945 0.1 7 3000 {'learning_rate': 0.1, 'max_depth': 7, 'n_esti... 27058.494221 33006.398437 36107.821603 32057.571420 3754.800132 43
28 43.130191 0.367656 0.087804 0.003051 0.01 8 2000 {'learning_rate': 0.01, 'max_depth': 8, 'n_est... 26904.997719 32957.109871 36495.731532 32119.279707 3959.967450 42
29 66.201859 1.078317 0.157360 0.037923 0.01 8 3000 {'learning_rate': 0.01, 'max_depth': 8, 'n_est... 26706.475723 32548.583114 37406.668019 32220.575618 4374.488197 41
27 90.449815 1.111693 0.210364 0.065813 0.01 7 4500 {'learning_rate': 0.01, 'max_depth': 7, 'n_est... 27100.255945 33024.068368 36602.108504 32242.144272 3918.320599 40
39 75.550887 1.133828 0.192195 0.052424 0.1 6 4500 {'learning_rate': 0.1, 'max_depth': 6, 'n_esti... 27715.506043 32654.882913 36428.633166 32266.340707 3567.713539 39
37 50.000066 0.262064 0.105703 0.002472 0.1 6 3000 {'learning_rate': 0.1, 'max_depth': 6, 'n_esti... 27501.133351 32749.516620 36920.065906 32390.238626 3853.646163 38
26 80.221079 1.206924 0.148606 0.002150 0.01 7 4000 {'learning_rate': 0.01, 'max_depth': 7, 'n_est... 27397.552661 33230.308448 36568.131463 32398.664191 3789.775984 37
46 90.909286 0.342673 0.304521 0.092288 0.1 8 4000 {'learning_rate': 0.1, 'max_depth': 8, 'n_esti... 27164.385685 32810.160003 37603.275391 32525.940360 4266.395057 36
38 66.324778 0.270104 0.139051 0.003221 0.1 6 4000 {'learning_rate': 0.1, 'max_depth': 6, 'n_esti... 27734.823997 32823.535114 37040.998993 32533.119368 3804.775880 35
36 34.073851 1.143685 0.076606 0.005565 0.1 6 2000 {'learning_rate': 0.1, 'max_depth': 6, 'n_esti... 27725.962321 32888.379474 37297.405822 32637.249206 3911.558298 34
40 38.122014 0.332359 0.083325 0.003782 0.1 7 2000 {'learning_rate': 0.1, 'max_depth': 7, 'n_esti... 27034.082970 32910.064968 38287.293026 32743.813655 4595.607596 33
25 59.330239 0.401193 0.118108 0.005652 0.01 7 3000 {'learning_rate': 0.01, 'max_depth': 7, 'n_est... 27747.879766 33614.775573 37069.674771 32810.776703 3847.837156 32
43 86.414162 0.571133 0.180650 0.002779 0.1 7 4500 {'learning_rate': 0.1, 'max_depth': 7, 'n_esti... 26881.837631 32933.227273 38874.121351 32896.395418 4895.898600 31
34 57.249265 1.073664 0.158692 0.062071 0.1 5 4000 {'learning_rate': 0.1, 'max_depth': 5, 'n_esti... 29408.726751 33627.684706 35892.075776 32976.162411 2686.610581 30
35 63.355886 0.801239 0.164848 0.045606 0.1 5 4500 {'learning_rate': 0.1, 'max_depth': 5, 'n_esti... 29333.217944 33648.154488 35993.049737 32991.474056 2758.231531 29
24 40.194203 0.346560 0.080205 0.001465 0.01 7 2000 {'learning_rate': 0.01, 'max_depth': 7, 'n_est... 28453.005068 34131.290608 37085.359579 33223.218418 3582.162515 28
33 42.553640 0.562150 0.135614 0.064287 0.1 5 3000 {'learning_rate': 0.1, 'max_depth': 5, 'n_esti... 29398.199700 33541.656656 36808.008219 33249.288192 3032.097741 27
32 28.663517 0.497557 0.060805 0.001500 0.1 5 2000 {'learning_rate': 0.1, 'max_depth': 5, 'n_esti... 29438.735499 33275.006402 37180.438421 33298.060107 3160.579023 26
23 77.376478 0.476759 0.158256 0.015617 0.01 6 4500 {'learning_rate': 0.01, 'max_depth': 6, 'n_est... 29102.572458 34230.678761 36692.684127 33341.978449 3161.728427 25
47 95.797445 12.316660 0.199383 0.030434 0.1 8 4500 {'learning_rate': 0.1, 'max_depth': 8, 'n_esti... 27445.928497 32920.014030 39759.590437 33375.177655 5037.323895 24
22 70.774131 1.752816 0.133887 0.004077 0.01 6 4000 {'learning_rate': 0.01, 'max_depth': 6, 'n_est... 29363.618118 34492.642441 36616.650419 33490.970326 3044.572182 23
21 53.920188 0.500501 0.121876 0.024603 0.01 6 3000 {'learning_rate': 0.01, 'max_depth': 6, 'n_est... 29658.531194 35166.153292 37533.692014 34119.458833 3299.112654 22
20 35.874719 0.698718 0.075182 0.005964 0.01 6 2000 {'learning_rate': 0.01, 'max_depth': 6, 'n_est... 30359.415875 35992.936824 38117.388731 34823.247143 3273.394382 21
19 69.968219 0.694217 0.172459 0.066133 0.01 5 4500 {'learning_rate': 0.01, 'max_depth': 5, 'n_est... 32163.284551 36441.876707 37940.902023 35515.354427 2447.998988 20
18 61.377284 0.956657 0.166379 0.048980 0.01 5 4000 {'learning_rate': 0.01, 'max_depth': 5, 'n_est... 32315.703451 36957.356214 39066.959593 36113.339753 2820.063559 19
15 93.536175 1.914607 0.307884 0.084104 0.001 8 4500 {'learning_rate': 0.001, 'max_depth': 8, 'n_es... 31225.308128 36800.980499 42484.727694 36837.005440 4596.709373 18
17 44.313169 0.746331 0.155480 0.050574 0.01 5 3000 {'learning_rate': 0.01, 'max_depth': 5, 'n_est... 32766.875012 37991.268490 40202.052430 36986.731977 3117.401270 17
14 84.234663 1.034313 0.223117 0.008894 0.001 8 4000 {'learning_rate': 0.001, 'max_depth': 8, 'n_es... 32506.082515 37866.834013 43815.209874 38062.708801 4619.008956 16
16 29.770455 0.847891 0.072116 0.017159 0.01 5 2000 {'learning_rate': 0.01, 'max_depth': 5, 'n_est... 33772.322979 39210.273230 42874.952007 38619.182739 3739.563680 15
11 85.479482 1.555881 0.232637 0.031831 0.001 7 4500 {'learning_rate': 0.001, 'max_depth': 7, 'n_es... 34027.880584 39762.594233 43795.492262 39195.322360 4007.734814 14
10 73.961832 0.824863 0.241916 0.072718 0.001 7 4000 {'learning_rate': 0.001, 'max_depth': 7, 'n_es... 35607.489677 41053.902050 45445.138624 40702.176784 4023.896718 13
13 61.803987 2.104239 0.171170 0.010868 0.001 8 3000 {'learning_rate': 0.001, 'max_depth': 8, 'n_es... 36483.243204 42219.355716 47753.874887 42152.157936 4601.461456 12
7 75.104251 0.976083 0.231277 0.077961 0.001 6 4500 {'learning_rate': 0.001, 'max_depth': 6, 'n_es... 38085.567985 43405.941979 46058.416359 42516.642108 3315.088585 11
6 66.074946 0.555168 0.162041 0.003330 0.001 6 4000 {'learning_rate': 0.001, 'max_depth': 6, 'n_es... 40363.813777 45410.668434 47566.356673 44446.946295 3018.357866 10
9 54.510358 0.732664 0.143031 0.004631 0.001 7 3000 {'learning_rate': 0.001, 'max_depth': 7, 'n_es... 40343.444810 46147.150608 49909.471672 45466.689030 3934.843364 9
3 65.611706 0.541547 0.208231 0.062784 0.001 5 4500 {'learning_rate': 0.001, 'max_depth': 5, 'n_es... 43878.559903 48234.992447 50817.483600 47643.678650 2863.494895 8
2 59.796489 2.145500 0.214671 0.111948 0.001 5 4000 {'learning_rate': 0.001, 'max_depth': 5, 'n_es... 46268.048941 50565.945948 52495.307953 49776.434281 2602.842703 7
5 49.385644 0.501132 0.122519 0.002297 0.001 6 3000 {'learning_rate': 0.001, 'max_depth': 6, 'n_es... 46165.720531 51161.210911 53464.999132 50263.976858 3046.707374 6
12 40.901974 0.553713 0.117778 0.007300 0.001 8 2000 {'learning_rate': 0.001, 'max_depth': 8, 'n_es... 45368.719185 51286.549730 56672.753109 51109.340675 4616.553406 5
8 36.054974 0.596280 0.107239 0.009890 0.001 7 2000 {'learning_rate': 0.001, 'max_depth': 7, 'n_es... 50857.294989 56799.755849 59705.990115 55787.680317 3682.668780 4
1 42.355151 0.256998 0.104862 0.001990 0.001 5 3000 {'learning_rate': 0.001, 'max_depth': 5, 'n_es... 53660.856488 57698.063279 59295.512692 56884.810820 2371.128045 3
4 33.043582 0.682123 0.091754 0.010151 0.001 6 2000 {'learning_rate': 0.001, 'max_depth': 6, 'n_es... 57634.562432 63446.501200 66743.970230 62608.344621 3765.829474 2
0 29.126036 0.351096 0.094684 0.017199 0.001 5 2000 {'learning_rate': 0.001, 'max_depth': 5, 'n_es... 67592.554417 71162.419522 75435.644798 71396.872912 3206.217187 1
In [ ]:
print('Время, затраченное на перебор: ', end_time_skl_C)
Время, затраченное на перебор:  4454.352991342545
In [ ]:
skl_boosting_best_C = GradientBoostingRegressor(**skl_boosting_C.best_params_)
new_row = {}
new_row['Library'] = 'SkLearn'
start_time = time.time()
skl_boosting_best_C.fit(datasets['C'][0], datasets['C'][2])
new_row['Training time'] = time.time() - start_time
new_row['Dataset'] = 'C'
new_row['Train MAE'] = mean_absolute_error(skl_boosting_best_C.predict(datasets['C'][0]), datasets['C'][2])
new_row['Test MAE'] = mean_absolute_error(skl_boosting_best_C.predict(datasets['C'][1]), datasets['C'][3])
df_optimized = df_optimized.append(new_row, ignore_index=True)
In [ ]:
parameters_xgb_B = {'n_estimators': [1000, 2000, 3000, 4000],
                    'max_depth': np.arange(4, 8),
                    'learning_rate': np.logspace(-5, -1, 5)}
In [ ]:
base_xgb = XGBRegressor()
xgb_boosting_B = GridSearchCV(base_xgb, parameters_xgb_B, scoring=scorer, cv=3)
start_time_xgb_B = time.time()
xgb_boosting_B.fit(datasets['B'][0], datasets['B'][2])
end_time_xgb_B = time.time() - start_time_xgb_B
In [ ]:
res_xgb_B = pd.DataFrame(pd.DataFrame(xgb_boosting_B.cv_results_))
res_xgb_B.sort_values(by='mean_test_score')
Out[ ]:
mean_fit_time std_fit_time mean_score_time std_score_time param_learning_rate param_max_depth param_n_estimators params split0_test_score split1_test_score split2_test_score mean_test_score std_test_score rank_test_score
19 6.344315 0.797392 0.053465 0.000849 0.0001 4 4000 {'learning_rate': 0.0001, 'max_depth': 4, 'n_e... 128903.744571 112372.352066 137600.086859 126292.061165 10463.438516 80
23 9.216025 1.431839 0.075169 0.000787 0.0001 5 4000 {'learning_rate': 0.0001, 'max_depth': 5, 'n_e... 128823.890457 112560.050141 137551.446840 126311.795813 10356.171811 79
18 5.470657 0.795613 0.040972 0.002226 0.0001 4 3000 {'learning_rate': 0.0001, 'max_depth': 4, 'n_e... 130067.894428 110891.865678 138368.797274 126442.852460 11506.552899 78
27 11.161374 0.080921 0.092573 0.001006 0.0001 6 4000 {'learning_rate': 0.0001, 'max_depth': 6, 'n_e... 129040.093550 112754.939487 137790.781179 126528.604739 10373.974627 77
22 6.774150 0.785906 0.058131 0.000904 0.0001 5 3000 {'learning_rate': 0.0001, 'max_depth': 5, 'n_e... 130107.163728 111176.498217 138445.682391 126576.448112 11409.106478 76
... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
13 6.857562 0.613911 0.082823 0.030239 0.00001 7 2000 {'learning_rate': 1e-05, 'max_depth': 7, 'n_es... 152935.819300 130698.341405 162494.820677 148709.660461 13320.393824 5
0 1.945663 0.643921 0.016389 0.000741 0.00001 4 1000 {'learning_rate': 1e-05, 'max_depth': 4, 'n_es... 154162.418908 132176.189925 163980.540834 150106.383222 13297.061162 4
4 1.876005 0.026027 0.020008 0.000176 0.00001 5 1000 {'learning_rate': 1e-05, 'max_depth': 5, 'n_es... 154200.237761 132179.701028 163982.328489 150120.755759 13299.960110 3
8 2.921511 0.854658 0.024650 0.000173 0.00001 6 1000 {'learning_rate': 1e-05, 'max_depth': 6, 'n_es... 154221.628935 132158.893099 163986.518217 150122.346750 13312.964007 2
12 3.544118 0.778685 0.030377 0.000230 0.00001 7 1000 {'learning_rate': 1e-05, 'max_depth': 7, 'n_es... 154225.299473 132188.591255 164003.302148 150139.064292 13305.811907 1

80 rows × 14 columns

In [ ]:
print('Время, затраченное на перебор: ', end_time_xgb_B)
Время, затраченное на перебор:  1549.3431255817413
In [ ]:
xgb_boosting_best_B = XGBRegressor(**xgb_boosting_B.best_params_)
new_row = {}
new_row['Library'] = 'XGB'
start_time = time.time()
xgb_boosting_best_B.fit(datasets['B'][0], datasets['B'][2])
new_row['Training time'] = time.time() - start_time
new_row['Dataset'] = 'B'
new_row['Train MAE'] = mean_absolute_error(xgb_boosting_best_B.predict(datasets['B'][0]), datasets['B'][2])
new_row['Test MAE'] = mean_absolute_error(xgb_boosting_best_B.predict(datasets['B'][1]), datasets['B'][3])
df_optimized = df_optimized.append(new_row, ignore_index=True)
In [ ]:
parameters_xgb_C = {'n_estimators': [1000, 2000, 3000, 4000],
                    'max_depth': np.arange(4, 8),
                    'learning_rate': np.logspace(-5, -1, 5)}
In [ ]:
base_xgb = XGBRegressor()
xgb_boosting_C = GridSearchCV(base_xgb, parameters_xgb_C, scoring=scorer, cv=3)
start_time_xgb_C = time.time()
xgb_boosting_C.fit(datasets['C'][0], datasets['C'][2])
end_time_xgb_C = time.time() - start_time_xgb_C
In [ ]:
res_xgb_C = pd.DataFrame(pd.DataFrame(xgb_boosting_C.cv_results_))
res_xgb_C.sort_values(by='mean_test_score')
Out[ ]:
mean_fit_time std_fit_time mean_score_time std_score_time param_learning_rate param_max_depth param_n_estimators params split0_test_score split1_test_score split2_test_score mean_test_score std_test_score rank_test_score
72 14.434062 0.019635 0.034572 0.000305 0.1 6 1000 {'learning_rate': 0.1, 'max_depth': 6, 'n_esti... 28221.045302 32904.471418 42774.965215 34633.493978 6066.096244 80
73 30.578289 1.319403 0.065610 0.002279 0.1 6 2000 {'learning_rate': 0.1, 'max_depth': 6, 'n_esti... 28127.611072 32884.810142 42890.820903 34634.414039 6152.718991 79
74 44.585433 0.768792 0.095326 0.002378 0.1 6 3000 {'learning_rate': 0.1, 'max_depth': 6, 'n_esti... 28149.177655 32930.691747 43052.114614 34710.661339 6212.922088 78
75 60.389124 0.691399 0.123221 0.000987 0.1 6 4000 {'learning_rate': 0.1, 'max_depth': 6, 'n_esti... 28192.465986 32968.893192 43117.558309 34759.639162 6223.325668 77
76 18.108787 1.337547 0.043712 0.002853 0.1 7 1000 {'learning_rate': 0.1, 'max_depth': 7, 'n_esti... 28157.184685 32740.148710 43526.056626 34807.796674 6442.408052 76
... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
13 34.928353 0.120411 0.068113 0.001778 0.00001 7 2000 {'learning_rate': 1e-05, 'max_depth': 7, 'n_es... 152610.368751 130933.612545 162697.419246 148747.133514 13252.126720 5
0 11.465496 0.786430 0.023126 0.000746 0.00001 4 1000 {'learning_rate': 1e-05, 'max_depth': 4, 'n_es... 154138.856240 132180.957508 164108.810323 150142.874690 13337.237289 4
12 17.843340 0.755464 0.037115 0.001939 0.00001 7 1000 {'learning_rate': 1e-05, 'max_depth': 7, 'n_es... 154061.921649 132304.423023 164106.412164 150157.585612 13273.394648 3
4 12.761647 0.246127 0.028559 0.001430 0.00001 5 1000 {'learning_rate': 1e-05, 'max_depth': 5, 'n_es... 154144.813917 132219.838958 164112.464494 150159.039123 13321.653837 2
8 15.856818 0.900463 0.032732 0.001002 0.00001 6 1000 {'learning_rate': 1e-05, 'max_depth': 6, 'n_es... 154100.283047 132307.254434 164075.622472 150161.053318 13265.128473 1

80 rows × 14 columns

In [ ]:
xgb_boosting_best_C = XGBRegressor(**xgb_boosting_C.best_params_)
new_row = {}
new_row['Library'] = 'XGB'
start_time = time.time()
xgb_boosting_best_C.fit(datasets['C'][0], datasets['C'][2])
new_row['Training time'] = time.time() - start_time
new_row['Dataset'] = 'C'
new_row['Train MAE'] = mean_absolute_error(xgb_boosting_best_C.predict(datasets['C'][0]), datasets['C'][2])
new_row['Test MAE'] = mean_absolute_error(xgb_boosting_best_C.predict(datasets['C'][1]), datasets['C'][3])
df_optimized = df_optimized.append(new_row, ignore_index=True)
In [ ]:
df_optimized
Out[ ]:
Library Dataset Training time Train MAE Test MAE Test MAe
0 LightGBM B 1.213783 154559.349840 147743.748683 NaN
1 LightGBM C 1.407351 100231.736770 93828.102015 NaN
2 CatBoost B 9.075782 94985.925688 122813.038634 NaN
3 CatBoost C 3.874970 15649.423625 24996.950803 NaN
4 SkLearn B 13.941813 154512.155174 NaN 147719.858057
5 SkLearn C 26.394384 65096.543477 66504.687109 NaN
6 XGB B 4.062781 150117.793224 138842.985706 NaN
7 XGB C 22.123866 150118.368232 138864.097081 NaN

:**Ваши пояснения для проверяющих (опционально):** В этом блоке добавил перебор для XGBRegressor и GradientBoostingRegressor. LightGBM и CatBoost в задании 7.1 (В SkLearn описался в MAE, не бейте, я не выдержал бы это еще раз запускать)


Обычнно перебор параметров и поиск по сетке это самая скучная часть работы, поскольку занимает много времени, но не гарантирует воспроизведение результата при небольшом изменении датасета, да и сетку надо переосмысливать при каждом обновлении.

Но сейчас мы поймём, что этого можно избежать, поскольку есть библиотека, которая всё сделает за нас!

Эмоции выполняющего в этот момент.png

index.png

HyperOpt¶

Нашего спасителя зовут HyperOpt. На первый взгляд hyperopt делает всё то же самое, что и grid search, а именно перебирает параметры. По факту же hyperopt превращает это в задачу оптимизации, используя некоторые эвристики для ускорения сходимости процесса. К тому же, он требует лишь информацию о границе интервалов, а не сами сетки. В теории это должно помочь нам добиться лучших результатов за более короткое время. Давайте попробуем это сделать.

Для данного эксперимента я рекомендую использовать lightgbm, поскольку она быстрее и с ней удобнее играться, но Вы можете воспользоваться любой библиотекой из представленных выше.

**Задание 8 (кросс-проверка, 4 балла)**¶

Данные: датасет со стоимостью подержанных автомобилей

Метрика: MAE

Цели: В данном задании следует выполнить следующие пункты:

  1. Взять любую библиотеку градиентного бустинга (можете взять самую быструю)
  2. Составить сетку перебора в hyperopt, включающую параметры n_estimators, max_depth, subsample и learning_rate в hyperopt. Вам могут понадобиться такие типы данных, как hp.choice, hp.qloguniform, hp.uniform и hp.quniform(можно также пользоваться np.arange). Также для округления значения типа float до целых чисел (4.0 -> 4) используйте scope.int.
  3. Реализуйте функцию, которая принимает на вход словарь параметров для регрессора, и при помощи cv оценивает его качество на датасете A (можно воспользоваться cross_val_score, а для ускорения поставить cv=3). Не забудьте о том, в каком виде lightgbm принимает категориальные признаки в numpy и что также надо передавать индексы категориальных признаков.
  4. Создайте объект trials=Trials(), который будет хранить информацию о процессе оптимизации.
  5. Используя функцию fmin, оптимизируйте Вашу функцию. Установите algo=tpe.suggest, trials=trials и max_evals, по крайней мере, 50. verbose=1 позволит видеть прогресс-бар по типу tqdm.
  6. Выведите получившиеся параметры. Нарисуйте график, показывающий значение loss в ходе оптимизации. Посчитайте качество на тесте при использовании лучших параметров (возвращаются после использования fmin).
  7. Сделайте выводы по результату.
In [ ]:
# B) your code goes right here
In [ ]:
np.log(10)
Out[ ]:
2.302585092994046
In [94]:
from hyperopt import STATUS_OK
import warnings
warnings.filterwarnings("ignore")

trials = Trials()

def quality(params):
    hype_reg = LGBMRegressor(**params)
    score = cross_val_score(estimator=hype_reg, X=datasets['A'][0], y=datasets['A'][2],
                            scoring=scorer, cv=3, n_jobs=-1)
    return {'loss': score.mean(), 'params': params, 'status': STATUS_OK}

grid = {
    'n_estimators': scope.int(hp.uniform(label='n_estimators', low=1000, high=8000)),
    'max_depth': scope.int(hp.uniform(label='max_depth', low=5, high=10)),
    'learning_rate': hp.loguniform(label='learning_rate', low=-5*np.log(10), high=-1*np.log(10)),
    'subsample': hp.uniform('subsample', 0, 1)
}

best = fmin(fn=quality,
            space=grid,
            algo=tpe.suggest,
            max_evals=50,
            trials=trials,
            verbose=1)
100%|██████████| 50/50 [12:05<00:00, 14.51s/trial, best loss: 44806.26409478744]
In [95]:
best_params = {
    'n_estimators': int(best['n_estimators']),
    'max_depth': int(best['max_depth']),
    'learning_rate': best['learning_rate']
}
best_params
Out[95]:
{'n_estimators': 5643, 'max_depth': 8, 'learning_rate': 0.0034572150875588066}
In [96]:
hipe_results_dict = {
    'params': [str(res['params']) for res in trials.results],
    'loss': [res['loss'] for res in trials.results]
}
hype_results = pd.DataFrame(hipe_results_dict)
hype_results['number_exp'] = np.arange(1, len(hype_results) + 1)
hype_results
Out[96]:
params loss number_exp
0 {'learning_rate': 0.00021097434780014055, 'max... 117975.298983 1
1 {'learning_rate': 1.5674185319356302e-05, 'max... 147669.774888 2
2 {'learning_rate': 0.014894179569640512, 'max_d... 48156.305141 3
3 {'learning_rate': 1.3409308438038141e-05, 'max... 152915.493518 4
4 {'learning_rate': 5.4276284277438666e-05, 'max... 115068.771086 5
5 {'learning_rate': 0.06438157366330471, 'max_de... 48262.096105 6
6 {'learning_rate': 0.03484281280542673, 'max_de... 48678.391514 7
7 {'learning_rate': 0.0021150525018872064, 'max_... 48302.736446 8
8 {'learning_rate': 0.0001386990730362737, 'max_... 115494.537527 9
9 {'learning_rate': 0.0012005988323997867, 'max_... 49117.712929 10
10 {'learning_rate': 4.11710479039315e-05, 'max_d... 125566.613368 11
11 {'learning_rate': 0.0623962914815884, 'max_dep... 48148.564433 12
12 {'learning_rate': 0.00593299647110192, 'max_de... 45179.655871 13
13 {'learning_rate': 4.1977204989385805e-05, 'max... 120285.863877 14
14 {'learning_rate': 0.00032441026131469256, 'max... 65220.670415 15
15 {'learning_rate': 0.050113670044975536, 'max_d... 48400.429996 16
16 {'learning_rate': 1.0588462158432378e-05, 'max... 146270.226042 17
17 {'learning_rate': 5.628753137655974e-05, 'max_... 132168.361965 18
18 {'learning_rate': 0.0020637295301053574, 'max_... 51239.497341 19
19 {'learning_rate': 0.0006285042754822551, 'max_... 60607.068247 20
20 {'learning_rate': 0.008460343643703497, 'max_d... 45346.061063 21
21 {'learning_rate': 0.008227911873631309, 'max_d... 45002.322816 22
22 {'learning_rate': 0.004767214523022965, 'max_d... 44936.714333 23
23 {'learning_rate': 0.016878975438369945, 'max_d... 47146.960595 24
24 {'learning_rate': 0.0036680654595618377, 'max_... 44896.360901 25
25 {'learning_rate': 0.0034572150875588066, 'max_... 44806.264095 26
26 {'learning_rate': 0.0023631212342858235, 'max_... 45722.335752 27
27 {'learning_rate': 0.0008249328993122533, 'max_... 48456.454098 28
28 {'learning_rate': 0.00036358782358098885, 'max... 52108.688083 29
29 {'learning_rate': 0.028308807838037155, 'max_d... 49425.322345 30
30 {'learning_rate': 0.0036459642480586667, 'max_... 45011.206564 31
31 {'learning_rate': 0.00014275872618368083, 'max... 82749.680988 32
32 {'learning_rate': 0.014229058278378217, 'max_d... 44952.403245 33
33 {'learning_rate': 0.0013291404474893292, 'max_... 47323.885279 34
34 {'learning_rate': 0.0034805216806142784, 'max_... 44989.629938 35
35 {'learning_rate': 0.0005910192399235374, 'max_... 48773.167904 36
36 {'learning_rate': 0.0908065073511676, 'max_dep... 48865.155959 37
37 {'learning_rate': 0.021579313892376578, 'max_d... 48641.602725 38
38 {'learning_rate': 0.007783348177315384, 'max_d... 45737.434523 39
39 {'learning_rate': 0.011364376328839083, 'max_d... 47206.640194 40
40 {'learning_rate': 0.001386453810783903, 'max_d... 46260.064316 41
41 {'learning_rate': 0.0002448013340791645, 'max_... 105227.319317 42
42 {'learning_rate': 0.0026652414387530353, 'max_... 44941.710278 43
43 {'learning_rate': 0.043014946569644455, 'max_d... 49457.807239 44
44 {'learning_rate': 8.231264850908573e-05, 'max_... 111937.448942 45
45 {'learning_rate': 0.0005106922096140575, 'max_... 51243.451018 46
46 {'learning_rate': 0.005180449800293493, 'max_d... 46044.820217 47
47 {'learning_rate': 2.3918664674273388e-05, 'max... 141017.863042 48
48 {'learning_rate': 0.0017058202604077397, 'max_... 45143.044066 49
49 {'learning_rate': 0.0008194269856340977, 'max_... 48529.841602 50
In [97]:
hype_results['loss'].min()
Out[97]:
44806.26409478744
In [106]:
import matplotlib.pyplot as plt

plt.figure(figsize=(15, 10))
plt.plot(hype_results['params'], hype_results['loss'], marker='o')
plt.title('Dependence of MAE on Parameters', fontsize=16)
plt.xlabel('Parameters', fontsize=14)
plt.ylabel('MAE', fontsize=14)
plt.xticks(fontsize=12)
plt.yticks(fontsize=12)
plt.grid(True)
plt.xticks([])
plt.show()
In [ ]:
hype_best = LGBMRegressor(n_estimators=best_params['n_estimators'],
                          max_depth=best_params['max_depth'],
                          learning_rate=best_params['learning_rate'])
hype_best.fit(datasets['A'][0], datasets['A'][2])
mae_hype_best = mean_absolute_error(hype_best.predict(datasets['A'][1]), datasets['A'][3])
In [102]:
print('Качество на тесте с лучшими параметрами: %f' % mae_hype_best)
Качество на тесте с лучшими параметрами: 33863.520998

Выводы: Все быстро и круто.

Предсказание зрительских симпатий¶

Ну что, детишки, а теперь перейдём к действительно важным вопросам.

Внимание! Следующее задание сдается в системе cv-gml.ru, задание Град. бустинг (ML) Для выполнения этого задания необходимо скачать датасет из задания. Здесь вы можете немного почитать про датасет и, при желании, поэкспериментировать. На cv-gml.ru загружайте уже готовый скрипт с подобранными параметрами для обучаемого регрессора. Релизовать код необходимо в шаблонном файле awards_prediction.py, который вы можете найти в проверяющей системе.


В некотором царстве, некотором государстве была развита кинопромышленность. Новые фильмы в этом государстве показывают по интернету, а пользователи после просмотра могут дать фильму некоторую "награду". Наша цель - предсказать число наград для фильма.

В нашем распоряжении имеются следующие данные:

awards - количество наград, полученных фильмом от пользователей (целевое значение)
potions - количество магических зелий, потраченных на создание спец-эффектов
genres - жанры созданного фильма
questions - количество вопросов, заданных пользователями на соответствующих форумах об этом фильме до премьеры
directors - режиссеры фильма (если неизвестны, то unknown)
filming_locations - области, в которых снимался фильм
runtime - продолжительность фильма в некоторых единицах, принятых в этом государстве
critics_liked - количество критиков из 100, присудивших награды фильму на предварительных закрытых показах
pre-orders - количество зрителей, заранее купивших билеты на первый показ
keywords - ключевые слова, описывающие содержание фильма release_year - год, во котором фильм был показан (конечно, в летоисчислении этого государства)

Следующие поля появляются несколько раз с разными значениями i:

actor_i_known_movies - количество известных фильмов актера i (i от 0 до 2)

actor_i_postogramm - количество подписчиков в социальной сети "по сто грамм" актера i (i от 0 до 2)

actor_i_gender - пол актера i (i от 0 до 2)

actor_i_age - возраст актера i (i от 0 до 2)


Внимание! Учтите, что при OHE кодировании признаки на обучении и тестировании должны совпадать! Если вы примените простое .get_dummies() или что-то подобное, то признаки на трейне и тесте получатся разные! Так что вам, вероятно, придётся придумать способ для того, чтобы сохранить их :)

Внимание! Нельзя исключать вероятность того, что злые силы добавили в наш датасет пропуски, поэтому лучше лишний раз как-нибудь заполнить пропущенные значения.

Подсказка: для работы с текстом можно воспользоваться методом TF-IDF (ключевые слова: TfIdfTransformer). Также может быть полезен CountVectorizer. Только учтите, что никто не гарантирует улучшение результата с использованием данных методов ;)

Внимание! В проверяющей системе имеется проблема с catboost. При использовании этой библиотеки, в скрипте с решением необходимо инициализировать метод с использованием train_dir как показано тут: CatBoostRegressor(train_dir='/tmp/catboost_info')

Задание 9 (ML задание, 27 баллов)¶

Данные: датасет с наградами за фильмы

Метрика: MAE

Цели: В данном задании следует выполнить следующие пункты:

  1. Взять любую библиотеку градиентного бустинга
  2. Используя предложенный датасет, обучить регрессор для предсказания awards (предоставляем полную свободу в настройках и выборе методов)
  3. Загрузить решение и получить качество на закрытой выборке больше порогового значения
In [ ]:
## your efficient code here

[Бонус] задание (2 балла)¶

Найдите мем про градиентный бустинг лучше, чем этот:

image.png

timeline_1663224945_00031.jpg

Конец¶

Ну что детишки... Можете добавлять еще 4 библиотеки в своё резюме датасаентиста!

(╯°□°)╯︵ ┻━┻ FLIP THAT TABLE.

┻━┻ ︵ ヽ(°□°ヽ) FLIP THIS TABLE.

┻━┻ ︵ \\('0')// ︵ ┻━┻ FLIP ALL THE TABLES

ಠ_ಠ Son... ಠ_ಠ Put. ಠ__ಠ The tables. ಠ___ಠ Back.

(╮°-°)╮┳━┳

(╯°□°)╯︵ ┻━┻ NEVER!!!!